• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ory / x / 15046509034

15 May 2025 01:40PM UTC coverage: 60.795% (-0.2%) from 61.006%
15046509034

Pull #857

github

web-flow
Merge 2689561d7 into 5c4b146a4
Pull Request #857: fix(jonnetsecure): prevent massive memory usage from misbehaving jsonnet script

23 of 47 new or added lines in 4 files covered. (48.94%)

2 existing lines in 1 file now uncovered.

7130 of 11728 relevant lines covered (60.79%)

0.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/jsonnetsecure/cmd.go
1
// Copyright © 2023 Ory Corp
2
// SPDX-License-Identifier: Apache-2.0
3

4
package jsonnetsecure
5

6
import (
7
        "bufio"
8
        "fmt"
9
        "io"
10

11
        "github.com/pkg/errors"
12
        "github.com/spf13/cobra"
13
)
14

15
const (
16
        MiB uint64 = 1024 * 1024
17
        // Generous limit including the peak memory allocated by the Go runtime, the Jsonnet VM,
18
        // and the Jsonnet script.
19
        // This number was acquired by running:
20
        // `echo -n '{"Snippet":"std.repeat(\"a\", 1000)"}' | rusage ./kratos jsonnet > /dev/null
21
        // which outputs among other things: `ballooned to 45,088kb in size` (i.e. ~45 MiB).
22
        // Thus we raise this number a bit for safety and call it a day.
23
        memoryLimit = 64 * MiB
24
)
25

26
func NewJsonnetCmd() *cobra.Command {
×
27
        var null bool
×
28
        cmd := &cobra.Command{
×
29
                Use:    "jsonnet",
×
30
                Short:  "Run Jsonnet as a CLI command",
×
31
                Hidden: true,
×
32
                RunE: func(cmd *cobra.Command, args []string) error {
×
NEW
33

×
NEW
34
                        // This could fail because current limits are lower than what we tried to set,
×
NEW
35
                        // so we still continue in this case.
×
NEW
36
                        SetVirtualMemoryLimit(memoryLimit)
×
NEW
37

×
38
                        if null {
×
39
                                return scan(cmd.OutOrStdout(), cmd.InOrStdin())
×
40
                        }
×
41

42
                        input, err := io.ReadAll(cmd.InOrStdin())
×
43
                        if err != nil {
×
44
                                return errors.Wrap(err, "failed to read from stdin")
×
45
                        }
×
46

47
                        json, err := eval(input)
×
48
                        if err != nil {
×
49
                                return errors.Wrap(err, "failed to evaluate jsonnet")
×
50
                        }
×
51

52
                        if _, err := io.WriteString(cmd.OutOrStdout(), json); err != nil {
×
53
                                return errors.Wrap(err, "failed to write json output")
×
54
                        }
×
55
                        return nil
×
56
                },
57
        }
58
        cmd.Flags().BoolVarP(&null, "null", "0", false,
×
59
                `Read multiple snippets and parameters from stdin separated by null bytes.
×
60
Output will be in the same order as inputs, separated by null bytes.
×
61
Evaluation errors will also be reported to stdout, separated by null bytes.
×
62
Non-recoverable errors are written to stderr and the program will terminate with a non-zero exit code.`)
×
63

×
64
        return cmd
×
65
}
66

67
func scan(w io.Writer, r io.Reader) error {
×
68
        scanner := bufio.NewScanner(r)
×
69
        scanner.Split(splitNull)
×
70
        for scanner.Scan() {
×
71
                json, err := eval(scanner.Bytes())
×
72
                if err != nil {
×
73
                        json = fmt.Sprintf("ERROR: %s", err)
×
74
                }
×
75
                if _, err := fmt.Fprintf(w, "%s%c", json, 0); err != nil {
×
76
                        return errors.Wrap(err, "failed to write json output")
×
77
                }
×
78
        }
79
        return errors.Wrap(scanner.Err(), "failed to read from stdin")
×
80
}
81

82
func eval(input []byte) (json string, err error) {
×
83
        var params processParameters
×
84
        if err := params.Decode(input); err != nil {
×
85
                return "", err
×
86
        }
×
87

88
        vm := MakeSecureVM()
×
89

×
90
        for _, it := range params.ExtCodes {
×
91
                vm.ExtCode(it.Key, it.Value)
×
92
        }
×
93
        for _, it := range params.ExtVars {
×
94
                vm.ExtVar(it.Key, it.Value)
×
95
        }
×
96
        for _, it := range params.TLACodes {
×
97
                vm.TLACode(it.Key, it.Value)
×
98
        }
×
99
        for _, it := range params.TLAVars {
×
100
                vm.TLAVar(it.Key, it.Value)
×
101
        }
×
102

103
        return vm.EvaluateAnonymousSnippet(params.Filename, params.Snippet)
×
104
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc