Skip to main content

agentshield/parser/
mod.rs

1pub mod json_schema;
2pub mod python;
3pub mod shell;
4pub mod typescript;
5
6use std::collections::HashSet;
7use std::path::Path;
8
9use crate::error::Result;
10use crate::ir::execution_surface::*;
11use crate::ir::{ArgumentSource, Language, SourceLocation};
12
13/// Result of parsing a single source file.
14#[derive(Debug, Clone, Default)]
15pub struct ParsedFile {
16    pub commands: Vec<CommandInvocation>,
17    pub file_operations: Vec<FileOperation>,
18    pub network_operations: Vec<NetworkOperation>,
19    pub env_accesses: Vec<EnvAccess>,
20    pub dynamic_exec: Vec<DynamicExec>,
21    /// Names of function parameters (for tool argument tracking).
22    pub function_params: Vec<FunctionParam>,
23    /// Function definitions discovered in source code.
24    pub function_defs: Vec<FunctionDef>,
25    /// Function call sites discovered in source code.
26    pub call_sites: Vec<CallSite>,
27    /// Variables holding sanitized values (e.g., `validPath = validatePath(x)`).
28    pub sanitized_vars: HashSet<String>,
29}
30
31/// A function parameter discovered in source code.
32#[derive(Debug, Clone)]
33pub struct FunctionParam {
34    pub function_name: String,
35    pub param_name: String,
36    pub location: SourceLocation,
37}
38
39/// A function definition discovered in source code.
40#[derive(Debug, Clone)]
41pub struct FunctionDef {
42    pub name: String,
43    pub params: Vec<String>,
44    pub is_exported: bool,
45    pub location: SourceLocation,
46}
47
48/// A function call site discovered in source code.
49#[derive(Debug, Clone)]
50pub struct CallSite {
51    /// The function being called.
52    pub callee: String,
53    /// Arguments passed, each classified.
54    pub arguments: Vec<ArgumentSource>,
55    /// The enclosing function name, if any.
56    pub caller: Option<String>,
57    pub location: SourceLocation,
58}
59
60/// Language parser trait. Each parser extracts security-relevant operations
61/// from source files.
62pub trait LanguageParser: Send + Sync {
63    fn language(&self) -> Language;
64    fn parse_file(&self, path: &Path, content: &str) -> Result<ParsedFile>;
65}
66
67/// Get the appropriate parser for a language.
68pub fn parser_for_language(lang: Language) -> Option<Box<dyn LanguageParser>> {
69    match lang {
70        Language::Python => Some(Box::new(python::PythonParser)),
71        Language::TypeScript | Language::JavaScript => Some(Box::new(typescript::TypeScriptParser)),
72        Language::Shell => Some(Box::new(shell::ShellParser)),
73        _ => None,
74    }
75}