> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/sast-and-sca/ocular/quickstart.md).

# Quickstart

Ocular is a command-line tool for static code analysis. Ocular can help you find and correct security vulnerabilities in programs with hundreds of thousands lines of code, including flaws that are extremely difficult to detect. It includes an interactive shell and powerful automation capabilities, all centered around a data structure specifically designed for vulnerability discovery: the [Code Property Graph](broken://spaces/ipGHZi9EkcpDlsNhtIeC/pages/9Ao3P5J5WOLmNyc9UULu).

This article introduces you to the basics of working with Ocular. You learn how to create and modify Code Property Graphs, how to query them using the Code Property Graph Query Language and about organisational commands at your disposal. If you have not yet installed Ocular, you can do so by following [these instructions](/sast-and-sca/ocular/install.md).

## Obtaining the Sample Program <a href="#obtaining-the-sample-program" id="obtaining-the-sample-program"></a>

Before you start Ocular, you should have a program ready to analyze. Clone the following git repository which contains a simple program named `X42`:

```
git clone git@github.com:ShiftLeftSecurity/x42.git
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

Let us start with a problem statement. Show - without running the program - that an input exists for which `X42` always writes a string to standard error (STDERR).

```
// X42.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
  if (argc > 1 && strcmp(argv[1], "42") == 0) {
    fprintf(stderr, "It depends!\n");
    exit(42);
  }
  printf("What is the meaning of life?\n");
  exit(0);
}
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

## Starting Ocular's Interactive Shell <a href="#starting-oculars-interactive-shell" id="starting-oculars-interactive-shell"></a>

Go ahead and launch Ocular in your shell:

```
sl ocular
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

A console session will start and you will see a prompt:

```
ocular>
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

The prompt you are looking at is the prompt of a Scala-based REPL. If you have no experience with Scala or read-eval-print-loops, don't worry, you can accomplish a lot with Ocular by focusing only on what its commands allow you to do. If you *are* familiar with Scala and REPLs, you may be pleasantly surprised at the flexibility it provides you with.

## Importing the Code <a href="#importing-the-code" id="importing-the-code"></a>

We create a Code Property Graph for the `X42` program using the command `importCode`, which requires the path to the source code to be passed as a first argument, and a project name as a second argument. In particular, `importCode` creates a new project directory and stores a binary representation of the Code Property Graph in it.

```
ocular> importCode(inputPath="./x42/c", projectName="x42-c")
Creating project `x42-c` for code at `x42/c`
... output omitted
res1: Option[Cpg] = Some(io.shiftleft.codepropertygraph.Cpg@31ed46c5)
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

![](/files/mlZo7QhbBaWAQlpvEVi9)note

If you see an error and a return value of `None`, you have probably pointed Ocular to the wrong input path for the directory containing the source code for the sample project.

## Querying the Code Property Graph <a href="#querying-the-code-property-graph" id="querying-the-code-property-graph"></a>

You are ready to analyze your first program using Ocular and the Code Property Graph. Code analysis in Ocular is done using the Code Property Graph Query Language, a domain-specific language designed specifically for work with the Code Property Graph. It contains practical representations of the various nodes found in the Code Property Graph, and useful functions for querying their properties and relationships between each other. The top-level entry point into a Code Property Graph loaded in memory, and the root object of the Code Property Graph Query Language is `cpg`. If you evaluate `cpg` at the prompt, the output is underwhelming:

```
ocular> cpg
res2: Cpg = io.shiftleft.codepropertygraph.Cpg@cb0d5241
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

Rest assured, a lot is hidden behind that simple statement. You will discover the full set of commands in time, but for now, you should learn a helpful Ocular trick: `TAB`-completion. In the Ocular prompt, type `cpg.`, do not press `ENTER`, but instead press `TAB`. You will see a list of available functions `cpg` supports:

```
ocular> cpg. 
all                            comment                        finding                        local                          newArgumentDescriptorSource    newReturnSource                runScript                      types
annotation                     configfile                     flow                           member                         newArgumentSink                newTagForMethodsWithFullName   scalaGraph                     write
argument                       cpg                            graph                          metaData                       newArgumentSource              newTagForParameter             sensitiveType
arithmetic                     dependency                     help                           method                         newExposedParameterSink        newTagForParameterWithIndex    sensitiveVariable
assignment                     dom                            id                             methodRef                      newExposedParameterSource      newTagForParameterWithIndexes  sink
blacklist                      exposedMethod                  identifier                     methodReturn                   newLiteralSource               packagePrefix                  source
call                           exposedOutputParameter         ioFlow                         namespace                      newMethodSummary               parameter                      tag
callChain                      exposedParameter               jsp                            namespaceBlock                 newReturnDescriptorSource      read                           transform
close                          file                           literal                        newArgumentDescriptorSink      newReturnSink                  returns                        typeDecl
```

![](/files/CRrxFX9wuboXxDrdB2dv)

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

TAB-completion is available for all CPGQL Directives, and for top-level commands. For more descriptive assistance, use the `help` command, like so:

```
ocular> help.cpg 
res3: String = """
Upon importing code, a project is created that holds an intermediate
representation called `Code Property Graph`. This graph is a composition of
low-level program representations such as abstract syntax trees and control flow
graphs, but it can be arbitrarily extended to hold any information relevant in
your audit, information about HTTP entry points, IO routines, information flows,
or locations of vulnerable code. Think of Ocular as a CPG editor.

In practice, `cpg` is the root object of the query language, that is, all query
language constructs can be invoked starting from `cpg`. For exanple,
`cpg.method.l` lists all methods, while `cpg.finding.l` lists all findings of
potentially vulnerable code."""
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

## Solving the Challenge <a href="#solving-the-challenge" id="solving-the-challenge"></a>

Now that we have a good set of basic commands, and a Code Property Graph loaded in memory, let us return to our `X42` program and the problem we want to solve using Ocular. To reiterate, the problem statement is *Show that an input exists for which the X42 program always writes a string to STDERR*. And this is the `X42` program:

```
// X42.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
  if (argc > 1 && strcmp(argv[1], "42") == 0) {
    fprintf(stderr, "It depends!\n");
    exit(42);
  }
  printf("What is the meaning of life?\n");
  exit(0);
}
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

There are two parts in the problem statement: 1. *does the program write anything to STDERR?*, and 2. *if there is a call writing to STDERR, is it conditional on a value passed in as argument to the `X42` program?*

Ocular makes answering both questions easy. To answer the first one, whether the program writes anything to STDERR, we can search for nodes of type `CALL` in the graph, and use the `where` directive to only select those calls which have connections to nodes of type `ARGUMENT` that have the string `stderr` as the value of their `CODE` property. We find exactly one:

```
ocular> cpg.call.where(_.argument.code("stderr")).l
res4: List[Call] = List(
  Call(
    id -> 24L,
    code -> "fprintf(stderr, \"It depends!\\n\")",
    name -> "fprintf",
    order -> 1,
    methodInstFullName -> None,
    methodFullName -> "fprintf",
    argumentIndex -> 1,
    dispatchType -> "STATIC_DISPATCH",
    signature -> "TODO assignment signature",
    typeFullName -> "ANY",
    dynamicTypeHintFullName -> List(),
    lineNumber -> Some(7),
    columnNumber -> Some(4),
    resolved -> None,
    depthFirstOrder -> Some(-8),
    internalFlags -> Some(4)
  )
)
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

With this query we have proven the first part of our problem statement correct, there is a place in the `X42` program that writes to STDERR. Let us move to the second part, the check whether the call that writes something to STDERR is conditional on a value passed as input to the `X42` program. Since we are analyzing a program written in `C`, we will search the Code Property Graph for the conventional `argc` or `argv` parameters of the `main` function as the input that potentially triggers the call which writes to STDERR.

Using the query from the previous step, we can use the `astParent` construct to find out more about the surroundings around the `fprintf` call by moving up in the hierarchy of the abstract syntax tree that is part of the Code Property Graph. Moving up one level in the AST hierarchy gives us a block; not very helpful:

```
ocular> cpg.call.where(_.argument.code("stderr")).astParent.l
res5: List[AstNode] = List(
  Block(
    id -> 23L,
    code -> "",
    order -> 2,
    argumentIndex -> 2,
    typeFullName -> "void",
    dynamicTypeHintFullName -> List(),
    lineNumber -> Some(6),
    columnNumber -> Some(46),
    depthFirstOrder -> Some(-24),
    internalFlags -> Some(0)
  )
)
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

Another layer up gives us an if statement, much better:

```
ocular> cpg.call.where(_.argument.code("stderr")).astParent.astParent.l
res6: List[AstNode] = List(
  ControlStructure(
    id -> 11L,
    code -> "if (argc > 1 && strcmp(argv[1], \"42\") == 0)",
    columnNumber -> Some(2),
    lineNumber -> Some(6),
    order -> 1,
    parserTypeName -> "IfStatement",
    argumentIndex -> 1,
    depthFirstOrder -> None,
    internalFlags -> None
  )
)
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

The `CODE` property of the `CONTROL_STRUCTURE` node you just found proves the second part of our problem statement correct, the call that writes to STDERR is conditional on `argc` and `argv`. Hence, the whole problem statement is correct.

## Closing the Project <a href="#closing-the-project" id="closing-the-project"></a>

Now that we've finished the analysis, let us close the project, which also unloads the Code Property Graph from memory. You do not have to worry about losing any data, because it will remain on disk in the `x42-c` project you created earlier with `importCode`. Close the project using the aptly-named `close`:

```
ocular> close 
2020-05-08 01:13:01.752 WARN clearing 105 references - this may take some time
2020-05-08 01:13:01.756 WARN cleared all clearable references
res7: Option[io.shiftleft.console.workspacehandling.Project] = Some(
  Project(
    ProjectFile("/home/user/x42/c", "x42-c"),
    /home/user/.shiftleft/ocular/workspace/x42-c,
    None
  )
)
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

As a final step, exit Ocular completly:

```
ocular> exit 
Bye!
Would you like to save changes? (y/N)
y
saving.
```

![](/files/DfHDmRpYn5HJOmhRtTva) ![](/files/P5vj8JOtHNJWVEvAqKym)

Congratulations, you have succesfully queried your first Code Property Graph using Ocular and the Code Property Graph Query Language! In subsequent articles, you will learn the more advanced features of Ocular and also how to use it to find your first real-world vulnerability.
