Skip to content

Comments

feat: context-aware analysis#22

Draft
psyray wants to merge 4 commits intorelease/v0.5.0from
feat/framework-context
Draft

feat: context-aware analysis#22
psyray wants to merge 4 commits intorelease/v0.5.0from
feat/framework-context

Conversation

@psyray
Copy link
Owner

@psyray psyray commented Mar 26, 2025

This change introduces context-aware analysis to Oasis, allowing it to consider the programming language and framework of the scanned codebase. Users can specify the language and framework via command-line arguments. Oasis will now automatically detect the technology stack based on file extensions and framework-specific files if the language is not manually specified. This context is then used to tailor the security analysis and provide more relevant results. Several language contexts (PHP, Python, JavaScript, Java, Ruby) with common frameworks have been added.

Summary by Sourcery

Introduce context-aware analysis to tailor security analysis based on the programming language and framework of the scanned codebase. The technology stack can be specified via command-line arguments, or automatically detected based on file extensions and framework-specific files. The context is then used to tailor the security analysis and provide more relevant results.

New Features:

  • Add context-aware analysis to Oasis, allowing it to consider the programming language and framework of the scanned codebase.
  • Implement automatic technology stack detection based on file extensions and framework-specific files.
  • Introduce command-line arguments for specifying the language and framework.
  • Add language contexts (PHP, Python, JavaScript, Java, Ruby) with common frameworks to tailor the security analysis.

This change introduces context-aware analysis to Oasis, allowing it to consider the programming language and framework of the scanned codebase. Users can specify the language and framework via command-line arguments. Oasis will now automatically detect the technology stack based on file extensions and framework-specific files if the language is not manually specified. This context is then used to tailor the security analysis and provide more relevant results. Several language contexts (PHP, Python, JavaScript, Java, Ruby) with common frameworks have been added.
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Mar 26, 2025

Reviewer's Guide by Sourcery

This pull request introduces context-aware analysis to Oasis. It allows users to specify the programming language and framework, or Oasis can automatically detect the technology stack. This context is then used to tailor the security analysis and provide more relevant results. The implementation includes adding command-line arguments, creating a TechnologyContextManager class, and modifying the analysis prompt to incorporate technology context.

Sequence diagram for technology stack detection

sequenceDiagram
    participant Oasis
    participant TechnologyContextManager
    Oasis->>TechnologyContextManager: detect_technology_stack()
    alt Language specified in args
        TechnologyContextManager->>TechnologyContextManager: _get_manual_technology_context()
        TechnologyContextManager->>TechnologyContextManager: _validate_language_context(language)
        alt Framework specified
            TechnologyContextManager->>TechnologyContextManager: _validate_framework_context(language, framework)
        end
    else No language specified
        TechnologyContextManager->>TechnologyContextManager: _auto_detect_stack()
        TechnologyContextManager->>TechnologyContextManager: _detect_primary_language(input_path)
        alt Language detected
            TechnologyContextManager->>TechnologyContextManager: _detect_framework(input_path, detected_language)
        end
    end
    TechnologyContextManager-->>Oasis: language, framework
Loading

Sequence diagram for security analysis with technology context

sequenceDiagram
    participant Oasis
    participant SecurityAnalyzer
    participant TechnologyContextManager
    Oasis->>SecurityAnalyzer: SecurityAnalyzer(...)
    alt Language detected
        Oasis->>SecurityAnalyzer: set_technology_context(language, framework)
        SecurityAnalyzer->>TechnologyContextManager: load_context(language, framework)
        SecurityAnalyzer->>SecurityAnalyzer: self.current_tech_stack = {language, framework}
    end
    SecurityAnalyzer->>SecurityAnalyzer: _build_analysis_prompt(vuln_name, vuln_desc, vuln_patterns, code)
    SecurityAnalyzer->>TechnologyContextManager: get_security_context()
    SecurityAnalyzer-->>Oasis: prompt
Loading

Updated class diagram for TechnologyContextManager

classDiagram
    class TechnologyContextManager {
        -contexts_dir: Path
        -loaded_context: Dict
        -tech_stack: Dict
        -language_extensions: Dict
        -framework_indicators: Dict
        +__init__(contexts_dir: str)
        +_load_language_configurations()
        +load_context(language: str, framework: Optional[str]) : Dict
        +detect_technology_stack() : Tuple[str, Optional[str]]
        +_get_manual_technology_context() : Tuple[Optional[str], Optional[str]]
        +_validate_language_context(language: str) : bool
        +_validate_framework_context(language: str, framework: str) : bool
        +_auto_detect_stack() : Tuple[Optional[str], Optional[str]]
        +_detect_primary_language(input_path: Path) : Optional[str]
        +_count_file_extensions(input_path: Path) : Dict[str, int]
        +_detect_framework(input_path: Path, language: str) : Optional[str]
        +_check_framework_indicators(input_path: Path, indicators: list) : bool
        +get_language_extensions(language: Optional[str]) : list
        +get_ignore_patterns() : list
        +get_security_context() : str
        +_load_yaml(path: Path) : Dict
    }
Loading

Updated class diagram for SecurityAnalyzer

classDiagram
    class SecurityAnalyzer {
        -args
        -llm_model: str
        -embedding_manager: EmbeddingManager
        -ollama_manager: OllamaManager
        -scan_model: str
        -tech_context: TechnologyContextManager
        -current_tech_stack: Dict
        +__init__(args, llm_model: str, embedding_manager: EmbeddingManager, ollama_manager: OllamaManager, scan_model: str)
        +set_technology_context(language: str, framework: Optional[str])
        +_get_vulnerability_details(vulnerability: Union[str, Dict]) : Tuple[str, str, list, str, str]
        +_build_analysis_prompt(vuln_name: str, vuln_desc: str, vuln_patterns: list, code: str) : str
    }
Loading

File-Level Changes

Change Details Files
Introduced context-aware analysis by adding command-line arguments for language and framework specification.
  • Added -l or --language argument to specify the programming language.
  • Added -f or --framework argument to specify the framework.
  • Modified the argument parser to include the new arguments.
oasis/oasis.py
Implemented automatic technology stack detection based on file extensions and framework-specific files.
  • Created a TechnologyContextManager class to handle language and framework detection.
  • Implemented logic to detect the technology stack based on file extensions.
  • Implemented logic to detect the framework based on framework-specific files.
  • Added logic to use all supported extensions if no language or extensions are specified.
oasis/oasis.py
oasis/context_manager.py
Enhanced security analysis by incorporating technology context.
  • Modified SecurityAnalyzer to accept a TechnologyContextManager instance.
  • Added a set_technology_context method to SecurityAnalyzer to load the context.
  • Modified the analysis prompt to include technology context information.
  • Added language-specific configurations in the oasis/contexts directory.
oasis/analyze.py
oasis/oasis.py
oasis/context_manager.py
oasis/contexts/javascript/config.yaml
oasis/contexts/php/config.yaml
oasis/contexts/python/config.yaml
oasis/contexts/java/config.yaml
oasis/contexts/php/laravel.yaml
oasis/contexts/php/symfony.yaml
oasis/contexts/python/django.yaml
oasis/contexts/ruby/rails.yaml
oasis/contexts/java/hibernate.yaml
oasis/contexts/java/spring.yaml
oasis/contexts/javascript/angular.yaml
oasis/contexts/javascript/express.yaml
oasis/contexts/javascript/next.yaml
oasis/contexts/javascript/nuxt.yaml
oasis/contexts/javascript/react.yaml
oasis/contexts/javascript/vue.yaml
oasis/contexts/php/codeigniter.yaml
oasis/contexts/php/drupal.yaml
oasis/contexts/php/wordpress.yaml
oasis/contexts/python/fastapi.yaml
oasis/contexts/python/flask.yaml
oasis/contexts/python/pyramid.yaml
oasis/contexts/python/tornado.yaml
oasis/contexts/ruby/sinatra.yaml
oasis/contexts/java/struts.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@psyray psyray linked an issue Mar 26, 2025 that may be closed by this pull request
@psyray psyray self-assigned this Mar 26, 2025
@psyray psyray marked this pull request as draft March 26, 2025 01:15
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @psyray - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider adding more context files for other languages and frameworks to expand the tool's capabilities.
  • The automatic technology detection logic could be made more robust by considering multiple factors.
Here's what I looked at during the review
  • 🟡 General issues: 1 issue found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


return self.loaded_context

def detect_technology_stack(self) -> Tuple[str, Optional[str]]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Usage of self.args without initialization

Several methods (e.g. detect_technology_stack and _auto_detect_stack) reference self.args (like self.args.language and self.args.input_path) even though self.args is not set anywhere in TechnologyContextManager. To avoid runtime errors, consider either passing args during initialization or providing a mechanism to inject them before these methods are used.


logger = logging.getLogger(__name__)

class TechnologyContextManager:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider refactoring the TechnologyContextManager class into smaller, focused components such as a YAMLLoader and a TechnologyDetector to improve clarity and separation of concerns, and to inject dependencies explicitly to improve testability .

Consider breaking down the monolithic `TechnologyContextManager` into smaller, focused components to improve clarity and separation of concerns. For example:

1. **Extract YAML loading:**  
   Create a dedicated utility class for YAML loading. This isolates file I/O and error handling from context management.
   ```python
   class YAMLLoader:
       @staticmethod
       def load(path: Path) -> Dict:
           try:
               if path.exists():
                   with open(path) as f:
                       return yaml.safe_load(f)
               logger.warning(f"File not found: {path}")
           except Exception as e:
               logger.error(f"Error loading {path}: {e}")
           return {}

Then update your manager:

def _load_yaml(self, path: Path) -> Dict:
    return YAMLLoader.load(path)
  1. Separate auto-detection logic:
    Move technology stack detection (both manual and automatic) into a dedicated detector class. This reduces method responsibilities in your context manager.

    class TechnologyDetector:
        def __init__(self, args, language_extensions, framework_indicators):
            self.args = args
            self.language_extensions = language_extensions
            self.framework_indicators = framework_indicators
    
        def get_manual_context(self) -> Tuple[Optional[str], Optional[str]]:
            language = self.args.language.lower()
            framework = getattr(self.args, 'framework', None)
            framework = framework.lower() if framework else None
            return language, framework
    
        def auto_detect_context(self, input_path: Path) -> Tuple[Optional[str], Optional[str]]:
            # ... perform detection using language_extensions and framework_indicators ...
            return detected_language, detected_framework

    Then your manager can delegate detection:

    def detect_technology_stack(self) -> Tuple[str, Optional[str]]:
        detector = TechnologyDetector(self.args, self.language_extensions, self.framework_indicators)
        if getattr(self.args, 'language', None):
            return detector.get_manual_context()
        detected = detector.auto_detect_context(Path(self.args.input_path))
        return detected
  2. Inject dependencies explicitly:
    Instead of accessing self.args directly throughout, inject an args dependency (or its required parameters) via the constructor. This makes dependencies explicit and easier to test.

    class TechnologyContextManager:
        def __init__(self, contexts_dir: str = "oasis/contexts", args=None):
            self.contexts_dir = Path(contexts_dir)
            self.args = args
            # ...

These focused changes keep functionality intact while reducing complexity and improving testability.

psyray added 3 commits March 26, 2025 03:18
…, Drupal, Nuxt, React, CodeIgniter, Symfony, and Sinatra Contexts

This commit significantly expands Oasis's vulnerability detection capabilities by adding nine new contexts: Java/Spring, PHP (WordPress, Drupal, CodeIgniter, Symfony), JavaScript (Nuxt, React), and Ruby (Sinatra). It also enhances the existing PHP Laravel context with more comprehensive vulnerability patterns. These additions provide more specific and accurate vulnerability detection across a wider range of popular frameworks.
This commit introduces significant improvements to technology context handling and enables more adaptive security analysis. It adds automatic technology stack detection, including support for multiple languages and frameworks, and integrates this context into the analysis process. Vulnerability patterns are now loaded based on the detected stack, and framework-specific patterns are merged with base patterns for more accurate analysis. Additionally, a new analysis context manager is introduced to streamline context setup and access during analysis. The commit also includes updates to the README to document the new features and command-line arguments. Finally, ignore patterns in context files are now quoted to prevent issues with special characters.
This change enhances the code readability of the TechnologyContextManager and updates the dependencies used for scanning. The logic for identifying file extensions and checking framework indicators is simplified. Additionally, the example command in the README is updated to reflect new preferred scanning models.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add targeted framework analysis

1 participant