■ SECURITY
How we keep your credentials safe
Last updated: May 1, 2026
MsgSchool reads your kid's Canvas and Skyward data on your behalf. To do that you give us a Canvas API token and (optionally) a Skyward username and password. This page tells you, plainly, what happens to those values inside our system — and equally importantly, what we cannot defend against.
We try to be straight about both.
Your sequestered per-user workspace
When you register, we provision a dedicated workspace for you on our server at a unique filesystem path keyed to your Telegram numeric ID. That workspace is yours alone. No other user's agent can read it. The encrypted credential ciphertexts, the agent's memory notes, the conversation context, and the data fetched on your behalf all live inside that one path and nowhere else. When you /delete, we remove that workspace in its entirety — there are no shared tables of credentials, no shared cache of grades, no other path your data has flowed to.
The AI agent that talks to you is also yours alone. It has its own memory, its own loaded persona, its own session, its own cached context. It is not a shared chatbot that pretends to be different things to different people — it is your agent, instantiated once for you, with no view onto any other user's data, and no way to be addressed by anyone but you. Two different parents asking it the same question do not get answers from the same running process; each conversation is its own isolated instance.
The threat we worry about most
The credential we treat as highest-risk is your Skyward password. A Canvas API token is recoverable — you go into Canvas settings, revoke it, and issue a new one in 30 seconds. A Skyward password, on the other hand, is the actual login. If a bad actor gets it, they can log in as you, change the password, view your home address, emergency contacts, sometimes the last 4 of an SSN, and in some districts they can update transportation routing for your kid. Account takeover is the worst case. Everything below is designed around that fear first.
Where your credentials live
- On disk:only as ciphertext, encrypted with a key bound to our server's hardware (Linux
systemd-credsmachine-bound key). A disk image stolen while the server is powered off contains only ciphertext — the key is not on the disk, it is held by the operating system kernel. We have no way to decrypt those files on any other machine. - In memory: only inside our tool daemon (
msgschool-toolsd) — a separate long-running process whose only job is to call Canvas and Skyward on your behalf. The decrypted plaintext is evicted from this process's memory after at most 10 minutes. - In your AI agent: never. This is the design point we want you to take away from this page. The agent that talks to you in Telegram does not have the credential file in its filesystem, does not receive the credential as a tool input, and does not see the credential value in any form. It calls a tool like
canvas.get_pulseand receives data — your kid's grades, missing assignments, attendance — but never the token or password that fetched them. - In our chat logs: never. When you paste a credential into the bot, it is replaced with
[scrubbed: canvas.token]in our database within milliseconds, and the original message is deleted from your Telegram chat about a second later. - In our backups: only as ciphertext. Each nightly backup is encrypted with an age recipient before it leaves the VM. We are in the process of moving the matching private key to fully offline storage; until that lands, the key is held in our operator credentials store on a separate host. See Security work in progress below.
The four defense layers, in the order they fire
We don't rely on a single defense. Each of these runs even if the others failed:
- Inbound scrubber.The instant a credential-shaped message arrives from Telegram, we redact it in our database and call Telegram's delete API to remove the original message from your chat history. This fires whether or not we can identify which service the credential is for — credential-shaped, but unclassifiable, still gets deleted.
- Behavioral rules on the AI agent.The agent's standing instructions explicitly forbid: reading the credential file, writing any script that contains a credential value, calling Canvas or Skyward directly, and echoing a credential into chat. The agent calls our tool daemon for every read. This is the layer that prevents the most common LLM-leak failure mode (a model helpfully "showing its work" with the actual values).
- Outbound scrubber. Every reply the agent composes runs through a filter that strips literal occurrences of your known credential bytes before the message reaches you. If the agent ever did try to echo your password, the filter catches it and you see
[redacted]instead of the value. - Periodic at-rest sweep.Every two minutes, a background scanner reads your in-memory credential bytes and greps every file in your agent's workspace for any plaintext occurrence. Anything found is replaced in place with
[redacted-credscan]. This catches anything that sneaks past the first three layers and would otherwise sit on disk and end up in a backup.
What we cannot defend against
We'd rather tell you these up front than have you discover them later.
- Compromise of our server itself. If an attacker gets root on our VM, they can read the in-memory credentials of the running tool daemon. No app-level mitigation prevents that — our defense is keeping the server hardened, patched, and not reachable from the public internet except through the Telegram webhook.
- Compromise of Telegram itself, your Telegram account, or your phone. The bot reaches you through Telegram. We can't protect a chat session that an attacker has already taken over from the device side.
- Telegram's own retention of deleted messages.When we delete your credential paste from your chat, Telegram tells both ends the message is gone. Telegram's internal retention policy for deleted messages is not something we control or can verify.
- Misuse of credentials by us. We use them to read your data and for nothing else, but you are trusting us on that. If that trust is a problem for your situation, MsgSchool is not the right tool for you.
If something happens, here's what to do
- Rotate the Canvas token: Canvas → Account → Settings → Approved Integrations → delete the MsgSchool token. Issue a new one and re-paste it to the bot. The old token is dead within seconds.
- Change the Skyward password: log into Skyward Family Access and change your password. Re-send the new value to the bot. (Note: Skyward session cookies often survive a password change for some hours; if you suspect an active session, contact your district IT to force a logout.)
- Wipe everything we have on you: DM the bot
/delete, then replyDeleteto confirm. We delete your account record, all conversation history, the agent's memory, and the encrypted credential files. The encrypted backup tarball is purged after 30 days.
Security work in progress
We're a small operation and continue to harden the platform. The two items currently in flight:
- Per-user OS-level isolation between the AI agent and the credential daemon. Today the protection that keeps the agent from reading the credential file is behavioral — playbooks, the four defense layers above, and process discipline. The structural version runs the agent under a separate operating-system user account that cannotread the daemon's files even if the agent code asked it to. That change is in design and waiting on a dependency in our underlying agent runtime.
- Off-site encrypted backups with an offline decryption key. Today backups are at-rest encrypted on the same VM. We're moving the backup target off-VM with a key held offline so that even total compromise of the live host doesn't expose historical state.
We'll update this page when each one ships.
Found something?
If you think you've found a security issue with MsgSchool, please email [email protected] with what you saw, what you tried, and how to reproduce it. We answer within 24 hours.