fix(apply): reject reserved module names in validate_bundle (parity)
The interactive create path rejects a module whose name shadows a built-in SDK namespace (`kv`, `secrets`, …) so `import "kv"` can't resolve to a user module, but `pic apply`'s `validate_bundle` skipped the check — a parity gap that let a manifest create what the dashboard forbids. Gate it on `ScriptKind::Module` and share the same `RESERVED_MODULE_NAMES` const (now `pub(crate)`); endpoints remain unrestricted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -260,7 +260,7 @@ async fn create_script<R: ScriptRepository, L: ExecutionLogRepository>(
|
||||
/// real KV bridge — defense against author confusion, not a security
|
||||
/// boundary (stdlib namespaces and module imports already live in
|
||||
/// disjoint Rhai scopes).
|
||||
const RESERVED_MODULE_NAMES: &[&str] = &[
|
||||
pub(crate) const RESERVED_MODULE_NAMES: &[&str] = &[
|
||||
"log",
|
||||
"regex",
|
||||
"random",
|
||||
|
||||
@@ -886,6 +886,15 @@ impl ApplyService {
|
||||
)));
|
||||
}
|
||||
let res = if s.kind == ScriptKind::Module {
|
||||
// Parity with the interactive create path (`api.rs`): a module
|
||||
// may not shadow a built-in SDK namespace, or `import "kv"`
|
||||
// could resolve to a user module instead of the real bridge.
|
||||
if crate::api::RESERVED_MODULE_NAMES.contains(&s.name.as_str()) {
|
||||
return Err(ApplyError::Invalid(format!(
|
||||
"script `{}`: reserved module name (shadows a built-in SDK namespace)",
|
||||
s.name
|
||||
)));
|
||||
}
|
||||
self.validator.validate_module(&s.source)
|
||||
} else {
|
||||
self.validator.validate(&s.source)
|
||||
|
||||
Reference in New Issue
Block a user