Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/actions/sentinel-pr-audit/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ branding:

inputs:
sentinel-version:
description: 'Version of @sentinel/cli to install (npm install -g @sentinel/cli@<version>)'
description: 'Deprecated. The CLI is built and installed from the checked-out repository.'
required: false
default: 'latest'
default: 'local'
github-token:
description: 'GitHub token for API calls (defaults to github.token)'
required: false
Expand All @@ -27,12 +27,12 @@ runs:
with:
node-version: 20

- name: Install Sentinel CLI
- name: Install Sentinel CLI from checkout
shell: bash
env:
SENTINEL_VERSION: ${{ inputs.sentinel-version }}
run: |
npm install -g @sentinel/cli@"$SENTINEL_VERSION"
npm ci
npm run build
npm install -g .

- name: Audit PR
id: audit
Expand All @@ -46,7 +46,7 @@ runs:
SENTINEL_OUTPUT: /tmp/sentinel-result.json
GH_TOKEN: ${{ inputs.github-token }}
run: |
sentinel pr-audit
sntnl pr-audit

- name: Report failure
if: failure() && steps.audit.outcome == 'failure'
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v4.3.0

- Added `sntnl hardening` with agile, strict, and CI preference profiles, independently configurable toggles, and an informational local audit of package scripts, `.npmrc`, and lockfile signals.
- Added the `sentinel-hardening` agent skill and detailed safety/coverage documentation.
- Added pnpm lockfile auto-detection to `audit-deps`, using the existing pnpm/Yarn Berry parser.
- Updated the PR audit action to build and use the CLI from the checked-out source.

## v4.2.0

- Added the `sentinel-cicd-guard` and `sentinel-disclosure-dossier` agent skills.
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ sntnl scan ./src
# Audit all dependencies
sntnl audit-deps

# Review dependency hardening, startup/lifecycle scripts, and package-manager config
sntnl hardening --path .
sntnl hardening --path . --json
sntnl hardening status
sntnl hardening preset strict
sntnl hardening toggle lockfile off

# Start network monitoring
sntnl network start

Expand Down Expand Up @@ -234,7 +241,7 @@ PR Bot auto-analyzes all open PRs across your repos, posts findings as PR commen

### 7. Security Guard

OS-level package manager interception and git hooks:
Package-manager shell wrappers and Git hooks. Guard applies where Sentinel's shell path/profile setup is active; it is not a kernel-level interceptor. Use the hardening audit for a local, informational review of startup/lifecycle scripts and package-manager configuration. The audit does not execute project code, install packages, or upload project content.

```bash
sntnl guard enable # Intercept npm/yarn/pip installs
Expand All @@ -244,6 +251,16 @@ sntnl prepush install # Block pushes with threats
sntnl install npm <pkg> # Scan then install
```

Security profiles store independent local preferences (`agile`, `strict`, or `ci`). The interactive menu can offer to install the existing Guard and SAST pre-commit integrations. The audit reports suspicious static patterns as review signals, not proof of malicious behavior. It does not edit `.npmrc`; disabling lifecycle scripts may break native dependencies and does not prevent runtime scripts. Package-age quarantine and provenance toggles are preferences only in this release.

```bash
sntnl hardening --path . # Local package and startup-script review
sntnl hardening --json # Machine-readable report
sntnl hardening menu # Choose a profile, toggle protections, or audit
```

See [Security Profiles](./docs/SECURITY_PROFILES.md) for scope, privacy behavior, and limitations.

### 8. Threat Intelligence Memory

```bash
Expand Down Expand Up @@ -676,6 +693,7 @@ Sentinel evidence (Tier 1) overrides model reasoning (Tier 4).
| [Risk Engine](./docs/risk-engine.md) | Risk scoring methodology |
| [Trust Model](./docs/TRUST_MODEL.md) | Evidence hierarchy and calibration |
| [Skills](./docs/SKILLS.md) | AI agent integration guide |
| [Security Profiles](./docs/SECURITY_PROFILES.md) | Package-manager hardening review and profile limitations |
| [CI/CD Security](./docs/CI_CD_SECURITY.md) | CI pipeline security |
| [Corpus](./docs/corpus.md) | Canonical profile system |
| [Replay System](./docs/replay-system.md) | Session replay architecture |
Expand Down
34 changes: 34 additions & 0 deletions docs/SECURITY_PROFILES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Sentinel CLI Security Profiles and Dependency Hardening

`sentinel hardening [audit|status|preset|toggle|menu]` reviews a JavaScript project and stores local hardening preferences in `~/.sentinel/security_profile.json`.

## Examples

```sh
sntnl hardening --path .
sntnl hardening --path . --json
sntnl hardening status
sntnl hardening preset agile
sntnl hardening preset strict
sntnl hardening toggle lockfile off
sntnl hardening menu
```

Available presets are `agile`, `strict`, and `ci`. They are starting configurations; individual protections are independent and can be switched on or off. Applying a preset only stores the profile. In the interactive menu, applying `strict` offers to install Guard wrappers and the existing SAST pre-commit hook; neither is silently installed. The menu toggle for Guard or pre-commit applies/removes that existing integration. The classified-data hook runs as part of Sentinel's SAST pre-commit integration.

## Audit behavior and trust boundary

The project audit reads `package.json`, `.npmrc`, and the first recognized lockfile (`pnpm-lock.yaml`, `package-lock.json`, or `yarn.lock`). It identifies startup/lifecycle scripts, passes script text through Sentinel Lite's local static rules, and reports selected lockfile URL/integrity signals. It does not execute project code, install dependencies, resolve packages, or make network requests. The JSON report includes `executedProjectCode: false` and `networkRequests: 0`.

The result is advisory. A script such as `node scripts/health-check.js` is a startup script, not automatically malicious. A suspicious static pattern is a signal for human review, not proof of exploitation. This command currently does not run the Sentinel Cloud full engine; Cloud full-engine scans consume subscription pulses and must be invoked through the separate, existing `sntnl pulse-scan` flow after explicitly enabling pulse mode.

## Current coverage and limitations

- `ignore-scripts` and `shamefully-hoist` are reported when present in the project `.npmrc`. Sentinel does not edit `.npmrc` automatically. Disabling lifecycle scripts can break native dependencies and does not stop scripts invoked at runtime.
- Lockfile review identifies URLs outside the public npm registry and missing `integrity` metadata in npm `package-lock.json` entries. It does not prove a custom registry is malicious, compare a downloaded tarball, or fully parse all pnpm lockfile semantics.
- Package age quarantine and SLSA/npm provenance are not enforced by this profile module yet. Their toggles record preferences only and the CLI labels them as not implemented here.
- `pnpm` content-addressable storage uses hardlinks to save space; ordinary writes through linked package files do not generally rewrite the store inode because package files are made read-only. This is not a security boundary against privileged processes or unsafe store permissions. Do not treat a shared-store poisoning scenario as established without a reproducible, platform-specific path.
- Guard wrappers affect shells where Sentinel's path/profile setup is active. They are not a kernel-level interceptor and can be bypassed by absolute paths, other shells, or direct runtime execution.
- A configured Cloud session never causes this audit to upload source or manifests automatically. The existing `pulse-scan` behavior is separate and explicitly consumes a pulse.

The module intentionally proposes inspection and operator-controlled integrations. It does not overwrite project policy or execute scripts while analyzing them.
3 changes: 3 additions & 0 deletions docs/SKILLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Architecture, installation, and reference for integrating Sentinel into any AI c
skills/
CONSTITUTION.md # Shared rules (referenced by all adapters)
GENERIC.md # Universal skill for any agent
sentinel-hardening/SKILL.md # Local dependency hardening review workflow

adapters/
claude/CLAUDE.md
Expand All @@ -33,6 +34,8 @@ install-skills.ps1 # Bootstrap for Windows

Each adapter contains the same core content (constitution rules, command reference, workflows, evidence policy) formatted for the target agent platform. Only the file format and syntax differ.

The focused `sentinel-hardening` skill is an additional project skill for agents that need package-manager posture reviews. It is distributed with the npm package and can be referenced directly by compatible agents; use `sntnl hardening --path .` for the deterministic local report. It does not execute scripts or upload code.

---

## Installation
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sntnl-cli",
"version": "4.2.0",
"version": "4.3.0",
"description": "Sentinel Security Intelligence — SAST, supply chain, threat intel, and Skills/MCP for AI coding agents.",
"main": "dist/cli/main.js",
"bin": {
Expand Down
28 changes: 28 additions & 0 deletions skills/sentinel-hardening/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: sentinel-hardening
description: Review npm, pnpm, and yarn project hardening posture with Sentinel CLI without executing project scripts or uploading source.
---

# Sentinel Dependency Hardening

Use this skill when a user asks to inspect package-manager configuration, startup or lifecycle scripts, `.npmrc`, or npm/pnpm/yarn lockfile signals.

## Workflow

1. Run `sntnl hardening --path <project> --json` for a local informational report.
2. Explain the difference between ordinary startup scripts and suspicious static findings. Do not call a script malicious solely because it invokes Node, a shell, or a network library.
3. Review `.npmrc` and lockfile signals in context. Custom registries may be legitimate; verify ownership and policy before recommending changes.
4. Offer profiles with `sntnl hardening preset agile|strict|ci`; explain they store preferences. In interactive mode, Strict asks before installing Guard wrappers and the SAST pre-commit hook.
5. Use `sntnl hardening toggle <toggle> on|off` for a specific preference. Explain that the age/provenance preferences are not enforcement integrations yet.
6. If a full Sentinel Cloud scan is requested, explain that `sntnl pulse-scan` sends the package manifest to Cloud and consumes one subscription pulse; never run it without explicit user choice.

## Safety constraints

- Never run `npm install`, `pnpm install`, project scripts, or build commands as part of this audit.
- Never change `.npmrc`, lockfiles, scripts, or hooks without explicit operator action. The interactive Strict preset and integration toggles ask before installing/removing existing hooks or Guard integrations.
- The hardening audit itself is local: it reads project metadata and runs static text rules only. It does not fetch packages or send source to Cloud.
- Treat scanner output as evidence to validate, not an automatic vulnerability verdict. Report what was observed, what remains unknown, and a practical next check.
- `ignore-scripts=true` can break legitimate packages and does not prevent runtime execution. Present it as a project-specific tradeoff, not a universal secure default.
- Do not describe Sentinel Guard shell wrappers as unbypassable or kernel-level protection.

See `docs/SECURITY_PROFILES.md` for command reference, stored-toggle semantics, coverage, and limitations.
10 changes: 7 additions & 3 deletions src/cli/hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,9 +485,10 @@ async function handleConfigurationMenu() {
console.log(pc.blue(' 4.') + pc.white(` ⭐ ${t('config_opt4')}`));
console.log(pc.blue(' 5.') + pc.white(` 🔐 ${t('config_opt5')}`));
console.log(pc.blue(' 6.') + pc.white(` 📝 Install/Uninstall SAST Pre-Commit Hook`));
console.log(pc.blue(' 7.') + pc.white(` 🔙 ${t('config_opt5')}`));
console.log(pc.blue(' 7.') + pc.white(' Security profiles & dependency hardening'));
console.log(pc.blue(' 8.') + pc.white(` 🔙 ${t('config_opt5')}`));

const action = await askQuestion(pc.blue(' ❯ ') + pc.bold(`${t('select_opt')} (1-7): `));
const action = await askQuestion(pc.blue(' ❯ ') + pc.bold(`${t('select_opt')} (1-8): `));

console.log('');
if (action === '1') {
Expand All @@ -514,9 +515,12 @@ async function handleConfigurationMenu() {
await runCommand(['precommit', 'status']);
}
await askQuestion(pc.dim(`\n${t('press_enter')}`));
} else if (action === '6') {
} else if (action === '8') {
printHeader();
break;
} else if (action === '7') {
await runCommand(['hardening', 'menu']);
await askQuestion(pc.dim(`\n${t('press_enter')}`));
} else {
console.log(pc.red(` ${t('invalid_sel')}`));
}
Expand Down
Loading
Loading