Sign In

@shieldly/iam-lint

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shieldly/iam-lint - npm Package Compare versions

Comparing version
1.0.0
to
1.1.0
+116
bin/iam-lint.js
#!/usr/bin/env node
/**
* iam-lint CLI — lint AWS IAM policy JSON files from the command line.
*
* Usage:
* iam-lint [--fail-on critical|high|medium|info] <file.json> [more.json ...]
*
* Designed for pre-commit and CI: exits 1 when any finding at or above the
* --fail-on threshold (default: high) is found, 0 otherwise.
*
* Files whose JSON has no Statement element (and no PolicyDocument.Statement)
* are skipped — this keeps broad file matchers (e.g. pre-commit `types: [json]`)
* safe against package.json and other non-policy JSON.
*
* No network calls, no AWS SDK. Powered by Shieldly (https://www.shieldly.io).
*/
import { readFileSync } from 'node:fs';
import process from 'node:process';
import { lint } from '../src/index.js';
const SEV_RANK = { info: 0, medium: 1, high: 2, critical: 3 };
function usage() {
console.log('Usage: iam-lint [--fail-on critical|high|medium|info] <file.json> [more.json ...]');
}
const args = process.argv.slice(2);
let failOn = 'high';
const files = [];
for (let i = 0; i < args.length; i++) {
const a = args[i];
if (a === '--help' || a === '-h') {
usage();
process.exit(0);
} else if (a === '--fail-on') {
const v = String(args[i + 1] || '').toLowerCase();
if (!(v in SEV_RANK)) {
console.error(
`iam-lint: invalid --fail-on value "${args[i + 1]}" (expected critical|high|medium|info)`
);
process.exit(2);
}
failOn = v;
i++;
} else if (a.startsWith('-')) {
console.error(`iam-lint: unknown option "${a}"`);
usage();
process.exit(2);
} else {
files.push(a);
}
}
if (!files.length) {
usage();
process.exit(2);
}
/** Pull a policy document out of parsed JSON, unwrapping PolicyDocument if present. */
function extractPolicy(parsed) {
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
if (parsed.Statement) return parsed;
if (parsed.PolicyDocument?.Statement) return parsed.PolicyDocument;
}
return null;
}
let failing = 0;
let parseErrors = 0;
for (const file of files) {
let raw;
try {
raw = readFileSync(file, 'utf8');
} catch (err) {
console.error(`${file}: cannot read file (${err.message})`);
parseErrors++;
continue;
}
let parsed;
try {
parsed = JSON.parse(raw);
} catch (err) {
console.error(`${file}: invalid JSON (${err.message})`);
parseErrors++;
continue;
}
const policy = extractPolicy(parsed);
if (!policy) continue; // not an IAM policy document — skip silently
const findings = lint(policy);
const flagged = findings.filter((f) => SEV_RANK[f.sev] >= SEV_RANK[failOn]);
if (!findings.length) continue;
console.log(`\n${file}`);
for (const f of findings) {
const marker = SEV_RANK[f.sev] >= SEV_RANK[failOn] ? '✖' : '·';
console.log(` ${marker} [${f.sev}] ${f.title}`);
console.log(` ${f.detail}`);
if (f.link) console.log(` https://www.shieldly.io${f.link}`);
}
failing += flagged.length;
}
if (failing || parseErrors) {
console.log(
`\niam-lint: ${failing} finding(s) at or above "${failOn}"${parseErrors ? `, ${parseErrors} unreadable file(s)` : ''}.`
);
console.log('Deeper AI-Powered analysis (free, no signup): https://www.shieldly.io/app/iam');
process.exit(1);
}
process.exit(0);
+8
-2
{
"name": "@shieldly/iam-lint",
"version": "1.0.0",
"version": "1.1.0",
"description": "Lightweight, static-heuristic AWS IAM policy linter — no network, no AWS SDK dependency",

@@ -22,4 +22,8 @@ "license": "MIT",

},
"bin": {
"iam-lint": "bin/iam-lint.js"
},
"files": [
"src/index.js"
"src/index.js",
"bin/iam-lint.js"
],

@@ -36,2 +40,4 @@ "engines": {

"least-privilege",
"pre-commit",
"cli",
"shieldly"

@@ -38,0 +44,0 @@ ],

@@ -33,2 +33,32 @@ # @shieldly/iam-lint

## CLI
The package ships an `iam-lint` command for CI and local use:
```bash
npx @shieldly/iam-lint policies/*.json
# or, installed globally:
iam-lint --fail-on medium policies/lambda-role.json
```
- Exits `1` when any finding at or above the `--fail-on` threshold is found (default: `high`).
- Files wrapped in a `PolicyDocument` key (CloudFormation-style) are unwrapped automatically.
- JSON files without a `Statement` element are skipped, so globbing broadly is safe.
## pre-commit hook
Lint IAM policies on every commit with [pre-commit](https://pre-commit.com):
```yaml
# .pre-commit-config.yaml
repos:
- repo: https://github.com/shieldly-io/iam-lint
rev: v1.1.0
hooks:
- id: iam-lint
files: ^policies/.*\.json$ # scope to your IAM policy files (optional but faster)
```
Pass CLI flags through `args`, e.g. `args: [--fail-on, medium]`.
## What this checks

@@ -35,0 +65,0 @@