Serpico Documentation

repository·master·Indexed 22 days ago

https://github.com/buffalowill/serpico

A penetration testing report generation and collaboration tool that automates the creation of information security reports using Microsoft Word templates and a shared findings database. It features a custom Meta-Language for mapping UI data to .docx files, a Template Database for reusing findings, and an attachment system for team collaboration. Installation is supported via Docker and Docker Compose.

Tokens
22.2K
Snippets
92
Records
118
Agent score
78%

What's inside Serpico

  1. Overview of CodeMirror

    master
    CodeMirror is a JavaScript-based text editor designed for the browser, specifically optimized for code editing. It features over 100 language modes providing syntax highlighting and a variety of addons for advanced editing capabilities. Developers can customize the editor using a rich programming API and a CSS-based theming system.
  2. How Serpico report generation works

    master

    Serpico is a penetration testing report generation tool that uses a template-based workflow:

    1. Findings: Users select "findings" from a central Template Database and add them to a report.
    2. Templates: A Report Template (in .docx format) defines the design of the final document. A default template is included, but users can upload their own via the UI.
    3. Meta-Language: Templates use a custom Microsoft Word Meta-Language to stub data (such as findings or customer names) from the Serpico UI into the Word document.
    4. Generation: Once sufficient findings are added, clicking 'Generate Report' produces the final .docx file.
  3. Use the Template Database for findings

    master

    To avoid writing findings from scratch, Serpico provides a Template Database.

    • Reuse: Authors can pull existing findings from the database and add them to a current report.
    • Contribute: Users can 'Upload' new findings they have created into the Template Database to make them available to the rest of the team.
  4. Collaborate using Attachments

    master

    Serpico includes an 'Add Attachment' feature designed for team collaboration during penetration tests. You can use this to:

    • Store files like screenshots or nmap scans.
    • Share files with teammates via the UI without using email or physical media.
    • Centralize all assets generated or traded during an assessment in one location.
  5. Build and run CodeMirror locally

    master

    To build the CodeMirror project from source, ensure you have Node.js (version 6 or higher) installed. You can then install dependencies and run the project using the following steps:

    1. Install dependencies: npm install
    2. Run the project: Open index.html directly in your browser (a webserver is not required).
    3. Run tests: Use npm test to execute the test suite.
    npm install
    npm test
  6. Create Report Templates with Microsoft Word Meta-Language

    master

    Serpico uses a custom Meta-Language within Microsoft Word to map UI data to the report.

    Best Practices:

    • The Meta-Language has a learning curve; it is highly recommended to avoid starting from scratch.
    • Instead, open existing template files such as Serpico - Report.docx or Serpico - No DREAD.docx and edit them to suit your needs.
    • Once you have modified a template, upload it back through the Serpico UI to use it for future reports.
  7. Install Serpico using Docker

    master

    The preferred method of installation is using Docker. This method sets up the necessary volumes for the database, temporary files, and attachments to ensure data persistence on your host machine.

    1. Create and enter a working directory:
      mkdir SERPICO
      cd SERPICO
    2. Run the Serpico Docker container, mapping port 8443 and mounting local directories for db, tmp, and attachments:
      docker run --name serpico -p 8443:8443 \
        -v"$(pwd)/db":/Serpico/db -v"$(pwd)/tmp":/Serpico/tmp \
        -v"$(pwd)/attachments":/Serpico/attachments \
        -it serpico/serpico
    3. Access the UI at https://127.0.0.1:8443.
    mkdir SERPICO
    cd SERPICO
    
    docker run --name serpico -p 8443:8443 \
      -v"$(pwd)/db":/Serpico/db -v"$(pwd)/tmp":/Serpico/tmp \
      -v"$(pwd)/attachments":/Serpico/attachments \
      -it serpico/serpico
  8. Understand the Context and State in mode parsing

    master

    Mode parsing relies on two main concepts:

    1. State: A user-defined object that tracks the current parsing status (e.g., whether we are inside a string or a comment). Use copyState(mode, state) to create a clone of the state to avoid side effects.
    2. Context: An object used during the highlighting process that tracks the current line, the document, and the state. It allows for lookAhead operations to see subsequent lines.

    When a mode needs to switch to a different mode (e.g., entering a nested block), it uses innerMode(mode, state) to return the new mode and its corresponding state.

  9. Understand the CodeMirror Display Update lifecycle

    master

    The DisplayUpdate object manages the process of synchronizing the editor's internal state with the DOM. When the document changes, CodeMirror calculates a DisplayUpdate to determine what needs to be redrawn.

    The Update Process

    1. Viewport Calculation: The editor determines which lines are visible based on the current scroll position and viewportMargin.
    2. View Adjustment: adjustView ensures the internal display.view covers the required range, adding or clipping elements as needed.
    3. DOM Patching: patchDisplay synchronizes the lineDiv DOM structure with the current display.view, adding new line nodes or updating existing ones.
    4. Post-Update: After the DOM is patched, the editor updates scrollbars, selection, and document height to match the new layout.
  10. How CodeMirror handles line heights and widgets

    master

    CodeMirror dynamically manages line heights to accommodate text and embedded widgets.

    • Estimation: When lines are not yet visible or measured, estimateHeight(cm) provides a first approximation. This calculation accounts for cm.options.lineWrapping and any widgets attached to the line.
    • Updating: updateHeightsInViewport(cm) reads actual DOM heights of rendered lines and updates the document's stored line heights. This ensures that scrolling and cursor positioning remain accurate.
    • Widgets: updateWidgetHeight(line) ensures that the height of widgets associated with a line is synchronized with their actual DOM height.
  11. Manage editor focus and blinking with `onFocus` and `onBlur`

    master

    CodeMirror manages focus state and cursor blinking through internal lifecycle methods.

    • Focusing: onFocus(cm, e) sets cm.state.focused = true, adds the CodeMirror-focused class to the wrapper, and restarts the cursor blink cycle via restartBlink(cm). If cm.options.readOnly is set to 'nocursor', focus behavior is restricted.
    • Blurring: onBlur(cm, e) sets cm.state.focused = false, removes the CodeMirror-focused class, and stops the cursor blink interval.
    • Blinking: The cursor blink rate is controlled by cm.options.cursorBlinkRate. A value > 0 enables blinking, while < 0 hides the cursor.
  12. Manage editor state changes with operations

    master

    CodeMirror uses an 'operation' pattern to batch multiple changes to the editor state. This prevents expensive and error-prone intermediate updates to the cursor and display. When you wrap changes in an operation, the display updates are deferred and executed all at once when the operation finishes.

    To run a function within an operation, use runInOp(cm, f). If an operation is already in progress, it executes the function immediately. Otherwise, it starts a new operation, runs the function, and ensures the operation is closed.

    To create a function that always runs within an operation (even if one is already active), use operation(cm, f).

    // Run a function within a new or existing operation
    runInOp(cm, function() {
      // Perform multiple editor changes here
      // The display will only update once at the end
    });
    
    // Create a reusable function that automatically handles operations
    const myWrappedFunction = operation(cm, function(arg1) {
      // Logic here
    });