Scaffold StepForge: docs, license, audit, npm project
- Environment audit and stack decision in build/agent_audit.md (Node + Electron shell over dependency-free core; deviation recorded) - Rewrite README/ARCHITECTURE/CONTRIBUTING for StepForge - Add SECURITY.md threat model, CODE_OF_CONDUCT.md, CHANGELOG.md, MPL-2.0 - Replace template grep checks with structural workflow check Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+69
@@ -0,0 +1,69 @@
|
||||
# Security
|
||||
|
||||
## Offline Guarantee
|
||||
|
||||
StepForge ships with **zero network code paths**. The application:
|
||||
|
||||
- opens no sockets and performs no HTTP requests,
|
||||
- has no telemetry, crash reporting, or analytics,
|
||||
- performs no update checks and no license validation,
|
||||
- has no account system, cloud sync, or remote AI integration,
|
||||
- embeds no remote fonts, CDNs, or external references in exports.
|
||||
|
||||
The only network activity in the project's lifetime is the one-time
|
||||
development fetch of the Electron shell via npm (see
|
||||
`build/agent_audit.md`). The packaged app never goes online.
|
||||
|
||||
## Threat Model
|
||||
|
||||
Because the app is local-only, the realistic attack surface is **malicious
|
||||
files opened by the user**:
|
||||
|
||||
### Archive imports (`.sfgz`, `.sfglt`)
|
||||
|
||||
Both formats are zip files. The reader in `core/zip.js` validates every entry
|
||||
before extraction:
|
||||
|
||||
- entry names must be relative, must not contain `..` segments, drive
|
||||
letters, or absolute paths;
|
||||
- entries are extracted only beneath the destination directory (resolved
|
||||
path is verified to stay inside it);
|
||||
- file sizes are taken from actual inflated data, not trusted headers;
|
||||
- unknown entries outside the documented layout are ignored.
|
||||
|
||||
### Image imports (PNG/JPEG/GIF)
|
||||
|
||||
Imported images are decoded by the platform image codecs in the Electron
|
||||
shell and re-encoded to PNG before storage. The pure-JS PNG decoder in
|
||||
`core/png.js` (used by exporters) rejects malformed dimensions, oversized
|
||||
allocations, and bad CRCs.
|
||||
|
||||
### Linked guides and lock files
|
||||
|
||||
Shared `.sfgz` files opened in *linked mode* use a sidecar lock file
|
||||
(`<name>.lock-sfgz`) containing the holder's machine name and timestamp.
|
||||
This is an advisory lock for coordination on shared folders, **not** a
|
||||
security boundary: a hostile or crashed peer can delete it. Conflicts are
|
||||
surfaced to the user with keep-editing / discard options; the format is
|
||||
last-write-wins and that risk is documented in the UI.
|
||||
|
||||
### Local data at rest
|
||||
|
||||
The guide store is **not encrypted at rest** — it inherits the user account's
|
||||
filesystem protections, like any document folder. If you need encrypted
|
||||
sharing, encrypt the `.sfgz` with external tooling; native encrypted archives
|
||||
are a tracked enhancement, not a current feature.
|
||||
|
||||
## Renderer Hardening
|
||||
|
||||
The Electron renderer runs with `contextIsolation: true` and
|
||||
`nodeIntegration: false`; the only privileged surface is the explicit
|
||||
allowlisted IPC API in `app/preload.js`. Guide description HTML is sanitized
|
||||
(allowlisted tags/attributes, no scripts, no event handlers, no external
|
||||
URLs) before storage and again before rendering or export.
|
||||
|
||||
## Reporting
|
||||
|
||||
Report vulnerabilities by opening an issue marked `security` (this is a
|
||||
local-only tool, so coordinated disclosure pressure is low; do not include
|
||||
exploit archives directly — describe the structure instead).
|
||||
Reference in New Issue
Block a user