Repository navigation
Move the security claims into the compiler and CI - #68
Merged
Merged
Conversation
The supply-chain layer was already here — cargo-deny, cargo-audit with a cron and a tracking issue, CodeQL, dependabot, pinned action SHAs, least-privilege tokens. What nothing checked was this product's own claims. "Nothing is written to your remote" is now a type. `wire::Verb` wraps a byte nothing outside that module can construct, and there are six of them: OPEN, CLOSE, READ, OPENDIR, READDIR, REALPATH. `SSH_FXP_WRITE`, SETSTAT, REMOVE, MKDIR, RMDIR, RENAME and SYMLINK are not missing by policy — there is no value of that type that means them, so the code that would send one does not compile. `Tx::queue` takes a `Verb` rather than a `u8`, which is the only way out. A seventh is a `pub const` somebody reads in a diff, and a test names the six and the eight write opcodes that are not among them. Unused `LSTAT` is gone. `unsafe_code = "forbid"` across the workspace. There is none today; `forbid` cannot be lifted by an `allow` further down, so there is none tomorrow without a build failure. `extension/permissions.json` pins what the extension can reach — permissions, host permissions, content scripts, web-accessible resources, externally connectable, CSP — and CI rebuilds it from the manifest and fails on a disagreement. This is the surface a reviewer asks about and the one that widens by accident, because a key added while doing something else looks like nothing in a diff full of TypeScript. Verified by adding `tabs` and watching it go red. zizmor lints the workflows themselves, failing rather than advising. Its first run found seventeen checkouts persisting credentials into `.git/config`, where every later step can read them and any artifact upload can carry them off the runner — release-plz already knew this and the rest had not caught up. All seventeen fixed; one remaining finding is suppressed inline with a reason. Pinned to the version this was verified against, and run through `pipx`, which is on the runner, so the linter needs no fourth-party SHA of its own. `npm audit --audit-level=high` on the extension. esbuild and typescript run on the machine that builds what gets signed, so a compromised one is a compromised build. 218 Rust tests, 63 e2e checks against a real host, zizmor clean. Signed-off-by: Souta <shimozono-sota631@g.ecc.u-tokyo.ac.jp>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #67 — merge that first.
The supply-chain layer was already here: cargo-deny, cargo-audit with a cron and a tracking issue, CodeQL, dependabot, pinned action SHAs, least-privilege tokens. What nothing checked was this product's own claims.
"Nothing is written to your remote" is now a type.
wire::Verbwraps a byte nothing outside that module can construct, and there are six:OPEN,CLOSE,READ,OPENDIR,READDIR,REALPATH.SSH_FXP_WRITE,SETSTAT,REMOVE,MKDIR,RMDIR,RENAME,SYMLINKare not missing by policy — there is no value of that type that means them, so the code that would send one does not compile.Tx::queuetakes aVerb, and that is the only way out of the process. UnusedLSTATis gone.unsafe_code = "forbid"across the workspace. There is none today, andforbidcannot be lifted by anallowfurther down.extension/permissions.jsonpins what the extension can reach and CI fails on any disagreement with the manifest. Verified by addingtabs:zizmor lints the workflows, failing rather than advising. First run:
Seventeen
actions/checkoutsteps persisting credentials into.git/config, where every later step can read them and any artifact upload can carry them off the runner.release-plz.ymlalready setpersist-credentials: false; the rest had not caught up. All fixed; the remaining low finding is suppressed inline with a reason, because it is on the one workflow whose first real run is a release.npm audit --audit-level=highon the extension — esbuild and typescript run on the machine that builds what gets signed.218 Rust tests, 63 e2e checks against a real SSH host, fmt/clippy/tsc clean.