Network/auth/delegate hardening
hdms
Added ls alias to list.
Made delegate failures explicit and nonzero in packages/bare-os-coreutils/src/hdms.js.
Added nonzero error exit in packages/bare-os-booter/lib/hdms-manager.js.
git-pear
Implemented clone subcommand routing to git clone in packages/bare-os-coreutils/src/git-pear.js.
trustctl
Added ls alias to status/policy output in packages/bare-os-coreutils/src/trustctl.js.
oidc-publish
Added explicit unknown-subcommand handling and publish subcommand compatibility in packages/bare-os-coreutils/src/oidc-publish.js.
ssh-keygen
Wrapped delegate invocation with explicit error propagation in packages/bare-os-coreutils/src/ssh-keygen.js.
Added success output on generated keypair in packages/bare-os-booter/lib/ssh-keygen-cli.js.
sshd
Added -t config test mode and explicit exit semantics in packages/bare-os-booter/lib/bare-openssh.js.
Ensured wrapper sets exit code consistently in packages/bare-os-openssh/src/sshd.js.
telnet
Changed connector preference to use net.createConnection first when available, then syscall bridge fallback, in packages/bare-os-coreutils/src/telnet.js.
crontab -e flow
Implemented edit flow with VISUAL/EDITOR fallback, unlocked-state checks, temp file handling, install, and cleanup in packages/bare-os-coreutils/src/crontab.js.
Shell/runtime hardcore semantics
Added numeric brace range expansion {1..5} in packages/bare-os-booter/lib/shell-glob.js.
Enabled brace expansion by default unless explicitly disabled.
Added normalization for inline brace-expression tokens in packages/bare-os-booter/lib/shell.js.
Added arithmetic command-form handling for (( ... )) in packages/bare-os-booter/lib/shell.js.
Extended shell signal trap dispatch support for USR1/USR2 (in addition to INT/TERM) in packages/bare-os-booter/index.js.
Hardened kill command delivery validation in packages/bare-os-coreutils/src/kill.js.
Regression tests
Added new: packages/bare-os-coreutils/test/hardcore-bugs.test.mjs.
Extended shell tests in packages/bare-os-booter/test.js for:
default cmdsub behavior,
brace range expansion,
arithmetic command form.
Existing regression files still pass after updates.
This commit is contained in:
@@ -137,6 +137,57 @@ async function run(ctx, argv) {
|
||||
return
|
||||
}
|
||||
|
||||
if (rest[0] === '-e') {
|
||||
if (ctx.identity?.state !== 'unlocked') {
|
||||
ctx.console.error('crontab: log in to edit crontab')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
if (typeof ctx.runBinCommand !== 'function') {
|
||||
ctx.console.error('crontab: -e requires runBinCommand support in this runtime')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const editorRaw = String(vfs.env?.VISUAL || vfs.env?.EDITOR || '').trim()
|
||||
const editor = editorRaw || 'edit'
|
||||
const editorParts = editor.split(/\s+/).filter(Boolean)
|
||||
if (!editorParts.length) {
|
||||
ctx.console.error('crontab: no editor configured')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const tmpPath = `${h}/.crontab.edit.${Date.now()}`
|
||||
try {
|
||||
const prev = await vfs.readFile(tabPath)
|
||||
await vfs.writeFile(tmpPath, prev || ctx.b4a.from(''))
|
||||
} catch (e) {
|
||||
ctx.console.error('crontab: failed preparing editor buffer: ' + (e?.message || e))
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
try {
|
||||
await ctx.runBinCommand([...editorParts, tmpPath])
|
||||
const edited = await vfs.readFile(tmpPath)
|
||||
if (edited == null) {
|
||||
ctx.console.error('crontab: edit aborted (temporary file missing)')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
await vfs.writeFile(tabPath, edited)
|
||||
ctx.console.log('crontab: installed')
|
||||
} catch (e) {
|
||||
ctx.console.error('crontab: edit failed: ' + (e?.message || e))
|
||||
ctx.exitCode = 1
|
||||
} finally {
|
||||
try {
|
||||
await vfs.unlink(tmpPath)
|
||||
} catch {
|
||||
/* ignore temp cleanup errors */
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (rest[0].startsWith('-')) {
|
||||
ctx.console.error('crontab: unknown option ' + rest[0])
|
||||
ctx.exitCode = 1
|
||||
|
||||
@@ -106,6 +106,24 @@ async function run(ctx, argv) {
|
||||
ctx.exitCode = 0
|
||||
return
|
||||
}
|
||||
if (sub === 'clone') {
|
||||
const url = String(argv[2] || '').trim()
|
||||
const dir = argv[3]
|
||||
if (!url) {
|
||||
ctx.console.error('git-pear clone: missing repository URL')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
if (typeof ctx.runBinCommand !== 'function') {
|
||||
ctx.console.error('git-pear clone: runBinCommand unavailable')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const args = ['git', 'clone', url]
|
||||
if (dir) args.push(String(dir))
|
||||
await ctx.runBinCommand(args)
|
||||
return
|
||||
}
|
||||
ctx.console.error('git-pear: unknown subcommand; use git-pear help')
|
||||
ctx.exitCode = 1
|
||||
}
|
||||
|
||||
+8
-1
@@ -88,9 +88,16 @@ function bareOsEmitRaw(ctx, chunk) {
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
if (argv[1] === 'ls') argv = [argv[0], 'list', ...argv.slice(2)]
|
||||
if (typeof ctx.runHdms === 'function') {
|
||||
await ctx.runHdms(argv)
|
||||
try {
|
||||
await ctx.runHdms(argv)
|
||||
} catch (e) {
|
||||
ctx.console.error('hdms: ' + ((e && e.message) || String(e)))
|
||||
ctx.exitCode = 1
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.console.error('hdms: unavailable')
|
||||
ctx.exitCode = 1
|
||||
}
|
||||
|
||||
+10
-1
@@ -170,7 +170,16 @@ async function run(ctx, argv) {
|
||||
for (const t of targets) {
|
||||
try {
|
||||
const resolved = bareOsKillResolveTarget(t, ctx)
|
||||
send.call(ctx, resolved, signal)
|
||||
const r = send.call(ctx, resolved, signal)
|
||||
if (
|
||||
r &&
|
||||
typeof r === 'object' &&
|
||||
r.delivered === false &&
|
||||
r.exists !== true &&
|
||||
r.ignored !== true
|
||||
) {
|
||||
throw new Error('signal not delivered')
|
||||
}
|
||||
} catch (e) {
|
||||
failed++
|
||||
ctx.console.error('kill: ' + t + ': ' + (e?.message || String(e)))
|
||||
|
||||
+10
-3
@@ -93,6 +93,7 @@ function bareOsEmitRaw(ctx, chunk) {
|
||||
*/
|
||||
async function run(ctx, argv) {
|
||||
const args = argv.slice(1)
|
||||
const sub = String(args[0] || '').trim()
|
||||
if (args.includes('help') || args.includes('-h') || args.includes('--help')) {
|
||||
ctx.console.log(`oidc-publish — optional OIDC token helper
|
||||
|
||||
@@ -108,10 +109,16 @@ async function run(ctx, argv) {
|
||||
ctx.exitCode = 0
|
||||
return
|
||||
}
|
||||
if (sub && sub !== 'publish') {
|
||||
ctx.console.error('oidc-publish: unknown subcommand ' + sub + ' (use `oidc-publish publish` or no subcommand)')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const env = ctx.vfs?.env || {}
|
||||
const issuer = String(env.OIDC_ISSUER || argv[2] || '').replace(/\/+$/, '')
|
||||
const cid = String(env.OIDC_CLIENT_ID || argv[3] || '')
|
||||
const csec = String(env.OIDC_CLIENT_SECRET || argv[4] || '')
|
||||
const base = sub === 'publish' ? 2 : 1
|
||||
const issuer = String(env.OIDC_ISSUER || argv[base + 1] || '').replace(/\/+$/, '')
|
||||
const cid = String(env.OIDC_CLIENT_ID || argv[base + 2] || '')
|
||||
const csec = String(env.OIDC_CLIENT_SECRET || argv[base + 3] || '')
|
||||
if (!issuer || !cid || !csec) {
|
||||
ctx.console.error(
|
||||
'oidc-publish: set OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET'
|
||||
|
||||
@@ -106,7 +106,12 @@ async function run(ctx, argv) {
|
||||
return
|
||||
}
|
||||
if (typeof ctx.bareOsRunSshKeygenCli === 'function') {
|
||||
await ctx.bareOsRunSshKeygenCli(argv)
|
||||
try {
|
||||
await ctx.bareOsRunSshKeygenCli(argv)
|
||||
} catch (e) {
|
||||
ctx.console.error('ssh-keygen: ' + ((e && e.message) || String(e)))
|
||||
ctx.exitCode = 1
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.console.error(
|
||||
|
||||
+24
-21
@@ -435,6 +435,29 @@ function bareTelnetResolveConnector(ctx) {
|
||||
return ctx.bareOsTelnetConnect(host, port, opts || {})
|
||||
}
|
||||
}
|
||||
var req = null
|
||||
try {
|
||||
if (typeof globalThis.require === 'function') req = globalThis.require
|
||||
} catch {
|
||||
req = null
|
||||
}
|
||||
if (!req && typeof Bare !== 'undefined' && Bare && typeof Bare.require === 'function') req = Bare.require
|
||||
if (req) {
|
||||
try {
|
||||
var net = req('net')
|
||||
if (net && typeof net.createConnection === 'function') {
|
||||
return function (host, port, opts) {
|
||||
return net.createConnection({
|
||||
host: host,
|
||||
port: port,
|
||||
family: opts && opts.family ? opts.family : undefined
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* fall through to syscall bridge */
|
||||
}
|
||||
}
|
||||
if (typeof ctx.bareOsSyscall === 'function') {
|
||||
return function (host, port, opts) {
|
||||
const handlers = new Map()
|
||||
@@ -548,27 +571,7 @@ function bareTelnetResolveConnector(ctx) {
|
||||
}
|
||||
}
|
||||
}
|
||||
var req = null
|
||||
try {
|
||||
if (typeof globalThis.require === 'function') req = globalThis.require
|
||||
} catch {
|
||||
req = null
|
||||
}
|
||||
if (!req && typeof Bare !== 'undefined' && Bare && typeof Bare.require === 'function') req = Bare.require
|
||||
if (!req) return null
|
||||
try {
|
||||
var net = req('net')
|
||||
if (!net || typeof net.createConnection !== 'function') return null
|
||||
return function (host, port, opts) {
|
||||
return net.createConnection({
|
||||
host: host,
|
||||
port: port,
|
||||
family: opts && opts.family ? opts.family : undefined
|
||||
})
|
||||
}
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function bareTelnetSleep(ms) {
|
||||
|
||||
+6
-2
@@ -474,7 +474,11 @@ async function run(ctx, argv) {
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
const policy = await bareOsTrustReadPolicy(ctx)
|
||||
if (sub === 'status' || (sub === 'policy' && String(args[1] || '') === 'show')) {
|
||||
if (
|
||||
sub === 'status' ||
|
||||
sub === 'ls' ||
|
||||
(sub === 'policy' && String(args[1] || '') === 'show')
|
||||
) {
|
||||
bareP2pPrint(ctx, policy, opt)
|
||||
return
|
||||
}
|
||||
@@ -523,7 +527,7 @@ async function run(ctx, argv) {
|
||||
bareP2pPrint(ctx, { ok: true, signerPins: policy.signerPins }, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, ['status', 'inspect', 'pin', 'policy'])
|
||||
const sug = bareP2pSuggestSubcommand(sub, ['status', 'ls', 'inspect', 'pin', 'policy'])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
|
||||
Reference in New Issue
Block a user