hackmyagent 0.11.2 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +22 -59
- package/dist/cli.js.map +1 -1
- package/dist/hardening/scanner.d.ts.map +1 -1
- package/dist/hardening/scanner.js +12 -146
- package/dist/hardening/scanner.js.map +1 -1
- package/dist/hardening/taxonomy.d.ts.map +1 -1
- package/dist/hardening/taxonomy.js +0 -1
- package/dist/hardening/taxonomy.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1538,43 +1538,22 @@ function resolvePackageVersion(targetDir) {
|
|
|
1538
1538
|
catch { /* ignore */ }
|
|
1539
1539
|
return null;
|
|
1540
1540
|
}
|
|
1541
|
-
/**
|
|
1542
|
-
* Build an anonymized contribution summary from scan findings.
|
|
1543
|
-
* Contains only aggregate data -- no file paths, no code, no project names.
|
|
1544
|
-
*/
|
|
1545
|
-
function buildContributionSummary(findings, score, projectType) {
|
|
1546
|
-
const failed = findings.filter((f) => !f.passed);
|
|
1547
|
-
const categories = [...new Set(failed.map((f) => f.category).filter(Boolean))].sort();
|
|
1548
|
-
const counts = { critical: 0, high: 0, medium: 0, low: 0 };
|
|
1549
|
-
for (const f of failed) {
|
|
1550
|
-
if (f.severity in counts)
|
|
1551
|
-
counts[f.severity]++;
|
|
1552
|
-
}
|
|
1553
|
-
return {
|
|
1554
|
-
packageType: projectType,
|
|
1555
|
-
findingCategories: categories,
|
|
1556
|
-
findingCounts: counts,
|
|
1557
|
-
score,
|
|
1558
|
-
toolVersion: index_1.VERSION,
|
|
1559
|
-
};
|
|
1560
|
-
}
|
|
1561
1541
|
/**
|
|
1562
1542
|
* Handle community contribution after a scan completes.
|
|
1563
1543
|
*
|
|
1564
1544
|
* Determines whether to contribute based on:
|
|
1565
1545
|
* 1. --contribute / --no-contribute CLI flags (highest priority)
|
|
1566
|
-
* 2.
|
|
1567
|
-
* 3.
|
|
1568
|
-
* 4. Interactive opt-in prompt (first scan or scan #10)
|
|
1546
|
+
* 2. ~/.opena2a/config.json contribute.enabled setting
|
|
1547
|
+
* 3. Interactive opt-in prompt (first scan or scan #10)
|
|
1569
1548
|
*
|
|
1570
|
-
*
|
|
1549
|
+
* If contributing, builds an anonymized payload and submits it
|
|
1550
|
+
* asynchronously (non-blocking). Failures are logged as warnings.
|
|
1571
1551
|
*/
|
|
1572
|
-
async function handleContribution(contributeFlag, targetDir, findings, registryUrl, format
|
|
1552
|
+
async function handleContribution(contributeFlag, targetDir, findings, registryUrl, format) {
|
|
1573
1553
|
try {
|
|
1574
1554
|
const { isContributeEnabled, shouldPromptContribute, showContributePrompt, incrementScanCount, buildContributionPayloadFromDir, submitContribution, } = await Promise.resolve().then(() => __importStar(require('./telemetry')));
|
|
1575
1555
|
// Always increment scan count
|
|
1576
1556
|
incrementScanCount();
|
|
1577
|
-
const isCi = contributionOptions?.ci === true;
|
|
1578
1557
|
// Determine whether to contribute
|
|
1579
1558
|
let shouldContribute;
|
|
1580
1559
|
if (contributeFlag === true) {
|
|
@@ -1585,10 +1564,6 @@ async function handleContribution(contributeFlag, targetDir, findings, registryU
|
|
|
1585
1564
|
// --no-contribute flag: skip this scan
|
|
1586
1565
|
shouldContribute = false;
|
|
1587
1566
|
}
|
|
1588
|
-
else if (isCi) {
|
|
1589
|
-
// CI mode: never prompt, only contribute if --contribute was explicit
|
|
1590
|
-
shouldContribute = false;
|
|
1591
|
-
}
|
|
1592
1567
|
else {
|
|
1593
1568
|
// Check config
|
|
1594
1569
|
const configSetting = isContributeEnabled();
|
|
@@ -1599,7 +1574,7 @@ async function handleContribution(contributeFlag, targetDir, findings, registryU
|
|
|
1599
1574
|
shouldContribute = false;
|
|
1600
1575
|
}
|
|
1601
1576
|
else {
|
|
1602
|
-
// Not configured -- prompt (interactive TTY only)
|
|
1577
|
+
// Not configured -- prompt after 3 scans (interactive TTY only)
|
|
1603
1578
|
if (format === 'text' && process.stdout.isTTY && shouldPromptContribute()) {
|
|
1604
1579
|
shouldContribute = await showContributePrompt();
|
|
1605
1580
|
}
|
|
@@ -1610,21 +1585,6 @@ async function handleContribution(contributeFlag, targetDir, findings, registryU
|
|
|
1610
1585
|
}
|
|
1611
1586
|
if (!shouldContribute)
|
|
1612
1587
|
return;
|
|
1613
|
-
// Build the anonymized contribution summary for transparency display
|
|
1614
|
-
const score = contributionOptions?.score ?? 0;
|
|
1615
|
-
const projectType = contributionOptions?.projectType ?? 'unknown';
|
|
1616
|
-
const summary = buildContributionSummary(findings, score, projectType);
|
|
1617
|
-
// Transparency: show what will be sent before sending
|
|
1618
|
-
if (format === 'text' && !isCi) {
|
|
1619
|
-
console.log('');
|
|
1620
|
-
console.log('Contributing anonymized scan summary to OpenA2A Registry:');
|
|
1621
|
-
console.log(` Package type: ${summary.packageType}`);
|
|
1622
|
-
console.log(` Categories: ${summary.findingCategories.join(', ') || '(none)'}`);
|
|
1623
|
-
console.log(` Findings: ${summary.findingCounts.critical} critical, ${summary.findingCounts.high} high, ${summary.findingCounts.medium} medium, ${summary.findingCounts.low} low`);
|
|
1624
|
-
console.log(` Score: ${summary.score}`);
|
|
1625
|
-
console.log(` Tool version: ${summary.toolVersion}`);
|
|
1626
|
-
console.log(' (No file paths, code, or project names are sent)');
|
|
1627
|
-
}
|
|
1628
1588
|
// Build and submit contribution (non-blocking)
|
|
1629
1589
|
const packageName = resolvePackageName(targetDir);
|
|
1630
1590
|
if (!packageName)
|
|
@@ -1646,7 +1606,7 @@ async function handleContribution(contributeFlag, targetDir, findings, registryU
|
|
|
1646
1606
|
* Converts SoulScanResult controls into SecurityFinding-like objects
|
|
1647
1607
|
* for the contribution module, then delegates to handleContribution.
|
|
1648
1608
|
*/
|
|
1649
|
-
async function handleSoulContribution(contributeFlag, targetDir, result, registryUrl, format
|
|
1609
|
+
async function handleSoulContribution(contributeFlag, targetDir, result, registryUrl, format) {
|
|
1650
1610
|
// Convert soul controls into SecurityFinding-shaped objects
|
|
1651
1611
|
const findings = [];
|
|
1652
1612
|
for (const domain of result.domains) {
|
|
@@ -1665,11 +1625,7 @@ async function handleSoulContribution(contributeFlag, targetDir, result, registr
|
|
|
1665
1625
|
});
|
|
1666
1626
|
}
|
|
1667
1627
|
}
|
|
1668
|
-
await handleContribution(contributeFlag, targetDir, findings, registryUrl, format
|
|
1669
|
-
ci: contributionOptions?.ci,
|
|
1670
|
-
score: result.score,
|
|
1671
|
-
projectType: 'soul',
|
|
1672
|
-
});
|
|
1628
|
+
await handleContribution(contributeFlag, targetDir, findings, registryUrl, format);
|
|
1673
1629
|
}
|
|
1674
1630
|
program
|
|
1675
1631
|
.command('secure')
|
|
@@ -1730,7 +1686,6 @@ Examples:
|
|
|
1730
1686
|
.option('--registry-key <key>', 'Registry API key (default: REGISTRY_API_KEY env)')
|
|
1731
1687
|
.option('--contribute', 'Share anonymized scan findings with OpenA2A Registry (overrides config)')
|
|
1732
1688
|
.option('--no-contribute', 'Do not share findings for this scan (overrides config)')
|
|
1733
|
-
.option('--ci', 'CI mode: suppress interactive prompts, machine-friendly output')
|
|
1734
1689
|
.action(async (directory, options) => {
|
|
1735
1690
|
try {
|
|
1736
1691
|
const targetDir = directory.startsWith('/') ? directory : process.cwd() + '/' + directory;
|
|
@@ -1935,7 +1890,7 @@ Examples:
|
|
|
1935
1890
|
writeJsonStdout(jsonOutput);
|
|
1936
1891
|
}
|
|
1937
1892
|
// Community contribution (non-blocking, runs in JSON mode too)
|
|
1938
|
-
await handleContribution(options.contribute, targetDir, result.findings, options.registryUrl, format
|
|
1893
|
+
await handleContribution(options.contribute, targetDir, result.findings, options.registryUrl, format);
|
|
1939
1894
|
const critHigh = result.findings.filter((f) => !f.passed && !f.fixed && (f.severity === 'critical' || f.severity === 'high'));
|
|
1940
1895
|
if (critHigh.length > 0)
|
|
1941
1896
|
process.exitCode = 1;
|
|
@@ -2015,10 +1970,11 @@ Examples:
|
|
|
2015
1970
|
? `${finding.file}:${finding.line}`
|
|
2016
1971
|
: finding.file
|
|
2017
1972
|
: '';
|
|
2018
|
-
// Format: SEVERITY file:line
|
|
1973
|
+
// Format: SEVERITY [DRY RUN] Would fix: file:line
|
|
2019
1974
|
// Description
|
|
2020
1975
|
// Fix: command
|
|
2021
|
-
|
|
1976
|
+
const dryRunPrefix = finding.wouldFix ? `${colors.cyan}[DRY RUN] Would fix: ${RESET()}` : '';
|
|
1977
|
+
console.log(`${display.color()}${display.symbol} ${finding.severity.toUpperCase()}${RESET()} ${dryRunPrefix}${location}`);
|
|
2022
1978
|
console.log(` ${finding.description}`);
|
|
2023
1979
|
if (finding.fix) {
|
|
2024
1980
|
console.log(` ${colors.cyan}Fix:${RESET()} ${finding.fix}`);
|
|
@@ -2056,6 +2012,14 @@ Examples:
|
|
|
2056
2012
|
if (summaryParts.length > 0) {
|
|
2057
2013
|
console.log(`${summaryParts.join(' | ')}\n`);
|
|
2058
2014
|
}
|
|
2015
|
+
// Dry-run summary
|
|
2016
|
+
if (result.dryRun) {
|
|
2017
|
+
const wouldFixCount = issues.filter((f) => f.wouldFix).length;
|
|
2018
|
+
if (wouldFixCount > 0) {
|
|
2019
|
+
console.log(`${colors.cyan}Dry run complete:${RESET()} ${wouldFixCount} issue${wouldFixCount === 1 ? '' : 's'} auto-fixable. Run without --dry-run to apply.`);
|
|
2020
|
+
}
|
|
2021
|
+
console.log(` No changes were made.\n`);
|
|
2022
|
+
}
|
|
2059
2023
|
}
|
|
2060
2024
|
// Print fixed findings
|
|
2061
2025
|
if (fixedFindings.length > 0) {
|
|
@@ -2155,7 +2119,7 @@ Examples:
|
|
|
2155
2119
|
}
|
|
2156
2120
|
}
|
|
2157
2121
|
// Community contribution: share anonymized findings with OpenA2A Registry
|
|
2158
|
-
await handleContribution(options.contribute, targetDir, result.findings, options.registryUrl, format
|
|
2122
|
+
await handleContribution(options.contribute, targetDir, result.findings, options.registryUrl, format);
|
|
2159
2123
|
// Star prompt (interactive TTY only, text format only)
|
|
2160
2124
|
if (process.stdout.isTTY) {
|
|
2161
2125
|
console.log(`${colors.cyan}Helpful?${RESET()} Star the project: https://github.com/opena2a-org/opena2a\n`);
|
|
@@ -4054,7 +4018,6 @@ Examples:
|
|
|
4054
4018
|
.option('--registry-url <url>', 'Registry URL (default: REGISTRY_URL env)', process.env.REGISTRY_URL || 'https://api.oa2a.org')
|
|
4055
4019
|
.option('--contribute', 'Share anonymized scan findings with OpenA2A Registry (overrides config)')
|
|
4056
4020
|
.option('--no-contribute', 'Do not share findings for this scan (overrides config)')
|
|
4057
|
-
.option('--ci', 'CI mode: suppress interactive prompts, machine-friendly output')
|
|
4058
4021
|
.action(async (directory, options) => {
|
|
4059
4022
|
try {
|
|
4060
4023
|
const targetDir = directory.startsWith('/') ? directory : process.cwd() + '/' + directory;
|
|
@@ -4220,7 +4183,7 @@ Examples:
|
|
|
4220
4183
|
}
|
|
4221
4184
|
// Community contribution: share anonymized findings with OpenA2A Registry
|
|
4222
4185
|
const soulFormat = options.json ? 'json' : 'text';
|
|
4223
|
-
await handleSoulContribution(options.contribute, targetDir, result, options.registryUrl, soulFormat
|
|
4186
|
+
await handleSoulContribution(options.contribute, targetDir, result, options.registryUrl, soulFormat);
|
|
4224
4187
|
// Check fail threshold
|
|
4225
4188
|
if (options.failBelow) {
|
|
4226
4189
|
const threshold = parseInt(options.failBelow, 10);
|