Spec It Safe — Kiro Power
Harden your Kiro specs with security primitives before code is written.
Spec It Safe (SIS) analyzes EARS-format requirements, detects which CWE/OWASP weaknesses each requirement is exposed to, and proposes traceable, testable security requirements to close the gaps. Security becomes a first-class construct in the spec — not an afterthought bolted on at code review.
Specify (EARS) → [ Spec It Safe ] → Plan → Execute
What's in this power
This repository is the power, packaged to the Agent Plugins v1.0.0 specification so Kiro can install it directly.
plugin.json # power manifest
skills/
harden-spec/ # workflow: run SIS over .kiro/specs and apply the results
security-primitives-reference/ # CWE→primitive knowledge base + methodology
cwe-to-spec-mapping-library/ # the bundled SIS engine (TypeScript CLI + library)
Two skills are exposed to the Kiro agent:
- harden-spec — locates your
.kiro/specs/*/requirements.md, runs the bundled engine, and walks you through the proposed security constraints and warnings, then applies them on confirmation. - security-primitives-reference — the CWE/OWASP knowledge base the agent uses to explain and justify each constraint, or to harden by hand.
Prerequisites
Install
Kiro IDE
Install it as a power. See Install powers for the full guide.
From GitHub:
- Open the Powers panel (the Ghosty icon with the lightning bolt).
- Click Add Custom Power, then Import power from GitHub.
- Enter
https://github.com/aws-samples/sample-kiro-spec-security-hardeningand click Install.
From a local folder:
-
Clone the repository:
git clone https://github.com/aws-samples/sample-kiro-spec-security-hardening.git spec-it-safe -
Open the Powers panel, click Add Custom Power, then Import power from a folder.
-
Choose the
spec-it-safedirectory (it containsplugin.json) and click Install.
From the Kiro powers registry (once published): browse kiro.dev/powers, select Spec It Safe, and click Add to Kiro.
Kiro CLI
Kiro CLI loads skills
from a project's .kiro/skills/ directory. Install the two skills there and
clone the engine inside the project, where the harden-spec skill can find it:
cd /path/to/your/project
git clone https://github.com/aws-samples/sample-kiro-spec-security-hardening.git .kiro/spec-it-safe
mkdir -p .kiro/skills
cp -R .kiro/spec-it-safe/skills/harden-spec .kiro/spec-it-safe/skills/security-primitives-reference .kiro/skills/
The engine is prebuilt
The bundled engine ships compiled in cwe-to-spec-mapping-library/dist/ and
has no runtime dependencies, so an installed power runs with Node.js alone.
To rebuild it after changing the source (contributors only):
cd spec-it-safe/cwe-to-spec-mapping-library # or .kiro/spec-it-safe/... for Kiro CLI
npm ci --ignore-scripts && npm run build
Commit the rebuilt dist/ together with the source change.
Quick start: try it on the bundled example
The repository ships a sample spec, examples/user-management.md, and its
expected hardened output, examples/user-management.hardened.md. To see SIS
work without writing a spec of your own:
cd spec-it-safe/cwe-to-spec-mapping-library
# The CLI hardens files in place, so work on a copy of the example.
# Keep the file name: constraint IDs are derived from it.
mkdir -p /tmp/sis-demo
cp examples/user-management.md /tmp/sis-demo/
node dist/cli/harden-requirements.js /tmp/sis-demo/user-management.md --semantic-candidates
# Compare with the expected result (no output means identical)
diff /tmp/sis-demo/user-management.md examples/user-management.hardened.md
To try it in Kiro, copy the example into a project as a spec, then ask Kiro to Harden my specs (see Run it):
mkdir -p /path/to/your/project/.kiro/specs/user-management
cp examples/user-management.md /path/to/your/project/.kiro/specs/user-management/requirements.md
Run it
In Kiro IDE
Open your project. Once your functional requirements are finalized, ask Kiro in the chat panel:
Harden my specs · Security-review the
checkoutspec · Harden.kiro/specs/payments/requirements.md
In Kiro CLI
Start a chat session from the project root and use the same prompts, or call the skill directly as a slash command:
cd /path/to/your/project
kiro-cli
> Harden my specs
> /harden-spec .kiro/specs/payments/requirements.md
What the skill does
In either client, the harden-spec skill:
- Finds the engine in the installed power by its absolute path.
- Lists your specs and confirms once. "Harden my specs" counts as consent
to harden every
.kiro/specs/*/requirements.md. Kiro only asks, in one question that lists the specs it found, when it's unclear which spec you mean. - Runs the compiled CLI with
--semantic-candidates, then does a semantic review pass for missing authorization checks that keyword matching can't see, adding domain-specific constraints by hand and curating generated ones that don't fit the system. It never edits requirement lines and never copies the spec. - Summarizes the requirements it hardened, the mandatory constraints grouped by CWE, the gaps it added in the semantic pass, and any warnings that need you to act.
The CLI prints every line it adds, so the changes can be reviewed even when
.kiro/ is not under version control. git diff works too when it is.
Standalone engine, without Kiro
Build once, then point the compiled CLI at one spec file or a whole specs
directory (directories are searched for .md files):
cd spec-it-safe/cwe-to-spec-mapping-library
# Harden every spec in a project
node dist/cli/harden-requirements.js /abs/path/to/project/.kiro/specs/
# Or one spec file
node dist/cli/harden-requirements.js /abs/path/to/project/.kiro/specs/my-feature/requirements.md
| Flag | Effect |
|---|---|
--semantic-candidates | Also print sub-threshold matches (mainly object-level authorization gaps) for manual or agent review. Printed only — never written to the file |
--semantic-all | With --semantic-candidates, list every sub-threshold CWE, not just authorization gaps (noisier) |
--semantic-floor <0-1> | Lowest score a sub-threshold match needs to be listed (default 0.05) |
--threshold <0-1> | Confidence a match needs before it fires (default 0.3) |
--max-proposals <n> | Most constraints added per requirement (default 10) |
--no-low-severity | Leave out low-severity CWEs |
--dry-run | Print the lines that would be added; write nothing |
--check | Validate only, write nothing: report requirements that are not strict EARS and malformed [SECURITY: …] lines (two obligations on one line, no actor, missing or duplicate ID). Exits 1 if anything is reported |
--mark-reviewed | Record the current requirements as reviewed without adding constraints. Use once on a file hardened by an older version, so later runs harden only what is added afterwards |
-h, --help | Show full usage |
Other ways to run it:
- From source, no build:
npm run harden -- <path> [flags]. This needs thetsxdevDependency. If you seetsx: command not found, runnpm install --include=dev. - As a global command: run
npm linkonce incwe-to-spec-mapping-library/, then callharden-requirements <path> [flags]from anywhere.
What it changes
It hardens each filename.md in place, and only by adding lines. Every
original line stays exactly as written: requirements are never split,
re-tagged, reworded or moved. Requirement-specific [SECURITY: …] constraints
are inserted under the requirement they harden, cross-cutting constraints are
consolidated into one ## Security Baseline (Cross-Cutting) section, and a
hidden <!-- spec-it-safe:reviewed … --> comment at the end records which
requirements were hardened. The CLI refuses to write if any original line
would not survive unchanged. No copies or sidecar files are written.
Constraints are chosen in the context of the whole document. A spec with no SQL database gets no SQL-injection constraints, a spec with no browser gets no CSP or CSRF constraints, and a topic the spec declares out of scope (for example "TLS is out of scope") gets no constraint that contradicts that decision. Withheld constraints are listed in the output. Constraints whose CWE matched only on loose keywords are flagged for review as possibly misplaced.
Requirements that are not strict EARS are reported, never rewritten. The check
is structural: it confirms the EARS keywords, a named actor such as
THE Chat_Server and a SHALL, but not that the response is complete. A
truncated requirement such as THE Chat_Server SHALL create. passes without a
warning, so the absence of warnings is not a completeness review.
Wording follows the spec, too. Templates have neutral defaults, and
technology-specific variants are used only when the spec has that technology
(e.g. "web-accessible document root" only for a web spec). Examples name the
spec's own language when it states one (e.g. Go encoding/gob instead of Java
and Python). Baseline constraints are written in the spec's system name
(THE Chat_System). A clause proposed under several criteria of one
requirement is written once. A constraint built from a placeholder the
requirement could not fill ("for the target") is flagged as a draft to
specialize. Every [SECURITY: …] line already in the file, hand-written ones
included, is checked on each run for one obligation per line, a named actor
and a unique ID; --check runs that validation alone.
Re-running is incremental: only requirements added or changed since the last
run are hardened, constraints a reviewer removed are not proposed again for
requirements already reviewed, and a file with nothing new is left untouched
([SKIP] … up to date).
Engine details, CLI options, and the programmatic API are documented in
cwe-to-spec-mapping-library/README.md.
Security
See CONTRIBUTING for more information.
License
This library is licensed under the MIT-0 License. See the LICENSE file.